日期: 2021 年 6 月 22 日

iOS钥匙串

iOS本地化存储信息
本地化不能存储明文,如果采用MD5 加密,因为MD5加密后都是64位的,过于复杂.所以本地采用钥匙串才是*明智的选择.
钥匙串是iOS7.0.3版本推出来的功能.(iCloud钥匙串),采用256位AES加密技术,用户的信息非常安全.
// 获取应用程序唯一标识.(一般我们都将程序的唯一标识作为钥匙串的Service的值)
// NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;
//存放信息
BOOL isStoreSuccess = [SSKeychain setPassword:@”myPassword” forService:@”kLoginKeyServiceName” account:@”Rephontil”];
//读取信息
NSString *password = [SSKeychain passwordForService:@”kLoginKeyServiceName” account:@”Rephontil”];
//log
NSLog(@”isStoreSuccess = %d, %@ %@”, isStoreSuccess,[SSKeychain allAccounts],password);
//删除对应的账户信息
//[SSKeychain deletePasswordForService:@”kLoginKeyServiceName” account:@”Rephontil”];
NSLog(@”isStoreSuccess = %d, %@ %@”, isStoreSuccess,[SSKeychain allAccounts],password);

使用钥匙串注意
温馨提示:使用钥匙串记得先在Capabilities里面打开Keychain Sharing的开关哦

 

iOS指纹登录

指纹登录简述
#pragma mark 指纹识别
//指纹识别功能是 iphone 5S之后推出的.SDK是 iOS 8.0 推出!
//推出指纹识别功能的目的,是为了简化移动支付环节,占领移动支付市场.
– (void)fingerPrintIdentification
{
// 1️⃣获得当前系统版本号
float version = [UIDevice currentDevice].systemVersion.floatValue;

if (version < 8.0 ) // 判断当前系统版本
{
NSLog(@”系统版本太低,请升级至*新系统”);
return;
}
// 2️⃣ 实例化指纹识别对象,判断当前设备是否支持指纹识别功能(是否带有TouchID)

// 1> 实例化指纹识别对象
LAContext *laCtx = [[LAContext alloc] init];

// 2> 判断当前设备是否支持指纹识别功能.
if (![laCtx canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:NULL]) {

// 如果设备不支持指纹识别功能
NSLog(@”该设备不支持指纹识别功能”);

return;
};

[laCtx evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@”指纹登陆” reply:^(BOOL success, NSError *error) {
// 如果成功,表示指纹输入正确.
if (success) {
NSLog(@”指纹识别成功!”);

} else {
NSLog(@”指纹识别错误,请再次尝试”);
}
}];

}

%title插图%num

 

iOS新项目的环境配置info.plist文件

iOS新项目的环境配置info.plist文件

Bundle ID有什么用? —–>用于产品上线,推送注册等。苹果根据Bundle ID找到手机上的这种应用,然后将后台消息推送给用户。
Bundle ID格式:类似于这样 com.tencent.wechat  (com.公司名.应用名)

上传的时候版本号不能相等,并且版本号必须要比之前的版本号大!(Version是应用在APP store里面展示的版本号,build是内部的打包测试的号,每一次打包,build号都需要自增,但是Version只有发布到App store成功以后,下次再发布才必须自增)

Development Target支持的iOS系统版本。

Main Interface(程序启动自动加载Main storeboard)

main.m文件里面的main函数所做的事情为以下4步:
1.创建一个UIApplication对象
2.创建UIApplication代理对象,并且成为UIApplication对象代理属性
3.开启主运行循环,保证程序一直跑起来,不立即结束(检测用户的触摸事件)
4加载info.plist文件,判断info.plist文件里面有没有执行main.stroeboard,如果指定就会加载main storeboard.

Main Interface指定程序启动的主窗口,默认指向scoreboard创建的主窗口,一般应用都是纯代码搭建主界面,这里Main Interface设置为空。

Device Oriention为设备支持的旋转方向。

status bar style :为状态栏的样式(即电源栏的样式高亮、默认,是否显示、隐藏)。

点击tabBar切换自控制器的原理:把上一个控制器view移除,然后把当前控制器view添加上去。
创建窗口,设置窗口的跟控制器,然后设置为主窗口。

App icon  项目图标。pt为点的单位,例如icon为29pt的图片,@2x的icon转换为像素就是 29*2 = 58个像素。
icon里面多余的图片都是在下面的unsigned上面,这些图片可以直接删掉,程序打包的时候不会打包这些没有使用的Appicon。

LaunchScreen:代理之前的启动图片。程序中碰到模拟器尺寸不对,马上找启动图片,默认模拟器的尺寸由启动图片决定。
LaunchScreen的好处:1可以展示更多的东西。  2 可以只求美工出一个大尺寸的图片。
启动图片的优先级Launch Images Sources:启动图片的优先级 < Launch Screen File,所以一般需要将后者设为空。

让iOS程序一直在后台运行

1 众所周知,iOS程序退入后台以后一段时间就会被杀死。那么如何保证一个应用程序进入后台以后一直保持活跃呢??通常*常见的方法就是在后台播放一段音频(没有声音),因为AVPlayer这个类进入后台以后可以保证程序不死。

首先我们需要在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法里面实现下面几段代码:

// 设置音频会话
AVAudioSession *session = [AVAudioSession sharedInstance];

// 后台播放
[session setCategory:AVAudioSessionCategoryPlayback error:nil];

// 单独播放一个后台程序
[session setCategory:AVAudioSessionCategorySoloAmbient error:nil];

[session setActive:YES error:nil];

2 在程序进入后台时,开启一个后台任务,时间不确定,这个优先级比较低,如果系统内存不足需要关闭应用的时候,系统首先会考虑关闭这个应用,但是总比不开启后台任务要好。

// 程序进入后台的时候调用
– (void)applicationDidEnterBackground:(UIApplication *)application {

// 开启一个后台任务,时间不确定,优先级比较低,假如系统要关闭应用,首先就考虑
UIBackgroundTaskIdentifier ID = [application beginBackgroundTaskWithExpirationHandler:^{

// 当后台任务结束的时候调用
[application endBackgroundTask:ID];

}];

// 如何提高后台任务的优先级,欺骗苹果,我们是后台播放程序

// 但是苹果会检测你的程序当时有没有播放音乐,如果没有,有可能就干掉你

// 微博:在程序即将失去焦点的时候播放静音音乐.

}

3 在程序即将不活跃的时候循环播放一段音频,是应用一直不被杀死。

// 失去焦点
– (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
NSURL *url = [[NSBundle mainBundle] URLForResource:@”silence.mp3″ withExtension:nil];
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[player prepareToPlay];
// 无限播放
player.numberOfLoops = -1;

[player play];

_player = player;
}

4.设置后台的模式

通过上面的4步骤就可以实现应用程序一直在后台运行了。

iOS 数据请求之网络层和数据层

在移动端开发中免不了要发送网络请求数据,一直以来我都没有数据层这个概念,偶然一次机会看网络视频,从一位叫MJ的大神那里获得“数据层”这个概念,在网络请求之后进行数据解析的时候尝试了下,发现层次感非常强��,代码的可读性很高,因此Mark一下。与君共勉!

下面将展示一个*常见的开发中例子:请求*新的列表数据。方法一非常常见:通常我们在请求的这个方法里面会进行参数赋值、字典数组与模型数组的转换等,使得请求的方法里面代码量很大,可读性差。

而!方法二是采用数据层的思想,已经将网络请求与数据处理彻底分开。因为在控制器里面只需要后的*新的数据,而不管请求这个过程,所以将网络请求这部分代码单独地抽取出来在一个工具类里面实现,抽取后的方法只需要我们提供请求所需要的动态参数,然后通过block将我们所需要的数据传递过来,代码的可读性强。推荐使用。
*#pragma mark –获取*新的数据(方法一 传统方法)*
– (void)getNewData
{
NSMutableDictionary *paraDic = [NSMutableDictionary dictionary];
paraDic[@”access_token”] = [ZYAccountTool account].access_token;

if (self.status.count) {
paraDic[@”since_id”] = [self.status.firstObject idstr];
}
[ZYHttpTool get:@”https://api.weibo.com/2/statuses/friends_timeline.json” parameters:paraDic progress:nil success:^(NSURLSessionDataTask *task, id responseObject) {
ZYLog(@”ZYHttpTool –>%@”,responseObject);

[self.tableView.mj_header endRefreshing];

// 字典数组
NSArray *dataArr = responseObject[@”statuses”];

NSArray *status = [ZYStatus mj_objectArrayWithKeyValuesArray:dataArr];

[self.status addObjectsFromArray:status];
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, status.count)];

// NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:status.count];
[self.status insertObjects:status atIndexes:indexSet];

[self.tableView reloadData];

} failure:^(NSURLSessionDataTask *task, NSError *error) {

}];

}

***#pragma mark –获取*新的数据(方法二 采用数据层思想的方法)***
– (void)otherMethodNewStatus
{
NSString *sinceId = nil;
if (self.status.count) {

sinceId = [self.status.firstObject idstr];

}
[ZYStatusTool newStatusWithSinceId:sinceId success:^(NSArray *modelArray) {

[self.tableView.mj_header endRefreshing];

NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, modelArray.count)];
[self.status insertObjects:modelArray atIndexes:indexSet];

[self.tableView reloadData];

} failure:^(NSError *error) {
ZYLog(@”失败了”);

}];
}

由上面两段代码明显看出:方法二目的性强,可读性高!简洁明了。

下面再看看数据层的代码封装方法:

/**
* 请求更新的微博数据
sinceId:返回比这个更大的微博数据
success:请求成功的时候回调(statuses(ZYStatus模型))
failure:请求失败的时候回调,错误传递给外界

*/
+ (void)newStatusWithSinceId:(NSString *)sinceId
success:(void(^)(NSArray *modelArray))success
failure:(void(^)(NSError *error))failure
{
ZYStatusPara *para = [ZYStatusPara sharedManager];
para.access_token = [ZYAccountTool account].access_token;

if (sinceId) {
para.since_id = sinceId;
}

[ZYHttpTool get:@”https://api.weibo.com/2/statuses/friends_timeline.json” parameters:para.mj_keyValues progress:nil success:^(NSURLSessionDataTask *task, id responseObject) {

NSArray *dicArray = responseObject[@”statuses”];

NSArray *modelArray = [ZYStatus mj_objectArrayWithKeyValuesArray:dicArray];

//只要请求成功了,就通过上面两步对返回的数据responseObject进行处理得到模型数组,然后将模型数组作为参数传递出去给外界使用!!
if (success) {
success(modelArray);
}

} failure:^(NSURLSessionDataTask *task, NSError *error) {

if (failure) {
failure(error);
}
}];

}

//数据层,我们将那些固定的参数都在这里处理完毕,只提供那些动态的参数字段供调用的时候赋值。

下面再看看对网络层的封装:网络层直接通过第第三方开源库AFNetWorking进行二次封装,这样以后整个工程改动的地方小,减少对AFNetWorking的依赖。

/**
GET请求方式

@param URLString 请求的主URL
@param parameters 请求参数
@param progress 进度
@param success 成功的回调
@param failure 失败的回调
*/
+ (void)get:(NSString *)URLString
parameters:(id)parameters
progress:(void(^)(NSProgress *downloadProgress))progress
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
// 获取http请求管理者
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];

[mgr GET:URLString parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
if (progress) {
progress(downloadProgress);
}

} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (success) {
success(task,responseObject);
}

} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure) {
failure(task, error);
}

}];

}

1. 两数之和(JS实现)

1. 两数之和(JS实现)
1 题目
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
2 思路
运用hashmap进行查找,节约时间
3代码
var twoSum = function(nums, target) {
    var map = {};
    for (var i=0;i<nums.length;i++) {
        if (typeof map[target – nums[i]] !== ‘undefined’) {
            return [map[target – nums[i]], i];
        } else {
            map[nums[i]] = i;
        }
    }
};

整数反转(JS实现)

整数反转(JS实现)
1 题目
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
2 思路
可以通过字符串数组反转,也可以整除反转
3代码
var reverse = function(x) {
    var s = (Math.abs(x) + ”).split(”).reverse().join(”);
    var num =  +(x < 0 ? ‘-‘ + s : s);
    var b = Math.pow(2, 31);
    return num >= b || num < (-b) ? 0 : num;
};

3. 无重复字符的*长子串(JS实现)

3. 无重复字符的*长子串(JS实现)

1 题目
给定一个字符串,请你找出其中不含有重复字符的 *长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的*长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的*长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的*长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

2 思路
这道题应用滑动窗口的概念,重点关注符合题目条件的子字符串的首字符位置,当没有重复字符时,首字符位置不变,当有重复时,首字符位置向后滑动至之前记录的重复字符位置

3代码
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
var map = {};
var maxLength = 0;
var x;
var first = 0;
for (var i=0;i<s.length;i++) {
x = s.charAt(i);
if (!(typeof map[x] === ‘undefined’ || map[x] < first)) { //若有字符重复,首字符串位置向后滑动
first = map[x] + 1;
}
map[x] = i; //记录新加入字符位置

if ((i – first + 1) > maxLength) {
maxLength = i – first + 1;
}
}

return maxLength;
};

5. *长回文子串(JS实现)

5. *长回文子串(JS实现)

1 题目
给定一个字符串 s,找到 s 中*长的回文子串。你可以假设 s 的*大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”

2 思路
这道题利用动态规划的方法,若一个字符串是回文字符串,那么在其首尾同时加上一个相同的字符得到的字符串也是回文字符串。在建立动态规划二维表时,首先判断1个字符和2个字符的情况,其他长度的字符串通过状态转移方程得出答案

3代码
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
var n = s.length;
var d = [];
for (var k=0; k<n; k++) {
d.push([]);
}

var ans = ”;
var j;
for (var l=1; l<=n; l++) { //l为子字符串字符长度
for(var i=0; i<n; i++) { //i为子字符串起始位置
j = i + l -1; //j为子字符串终止位置
if (j >= n) break;

if (i == j) {
d[i][j] = true;
} else if (j == i+1) {
d[i][j] = (s[i] == s[j]);
} else {
d[i][j] = d[i+1][j-1] && (s[i] == s[j]);
}

if (d[i][j] && ((j – i + 1) > ans.length)) {
ans = s.slice(i,j+1);
}
}
}

return ans;
};

6. Z 字形变换(JS实现)

6. Z 字形变换(JS实现)

1 题目
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入: s = “LEETCODEISHIRING”, numRows = 3
输出: “LCIRETOESIIGEDHN”
示例 2:
输入: s = “LEETCODEISHIRING”, numRows = 4
输出: “LDREOEIIECIHNTSG”
解释:
L D R
E O E I I
E C I H N
T S G

2 思路
这道题使用二维数组,刚开始我按照行列坐标进行填写,后来发现列不重要,只需要行就可以了,你会发现行号的变化是规律的

3代码
/**
* @param {string} s
* @param {number} numRows
* @return {string}
*/
var convert = function(s, numRows) {
if (numRows === 1) return s;

var d = [];
for (var i=0; i<numRows; i++) {
d.push([]);
}
var i = 0;
var flag = false;

for (var k=0; k<s.length; k++) {
d[getRows()].push(s[k]);
}

var ans = ”;
d.forEach(function(arr){
ans += arr.join(”);
});

return ans;

function getRows() {
if (i == numRows – 1 || i == 0) flag = !flag;
if (flag) {
return i++;
} else {
return i–;
}
}
};

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速