$ 朋友们 hello , 欢迎来到常见bug, 新的一页开始了,项目需求终于平衡于开发速度和bug处理, 还可以闲来记录一下下了~ 👉Now �begin ....
试问各类bug谁最泛滥, 那得莫过于"数组越界"了。好可恶是吧,那就严惩之~
试问各类卡顿总归于一因数 , 思考......... 一个解释 --> 耗时工作放在了主线程咯~
(一) crash列举一二
(1).数组
- 例1,
取值越界
- image.png
需要避免,👇
if (self.currentIdx >= _getAccostArr.count) {
return;
}
or
if (_getAccostArr.count == 0 || self.currentIdx > _getAccostArr.count - 1) {
return;
}
// 特别注意 , 在点击删除最后一个卡片时, 卡片有消失的动画时, 你连续点击删除,要小心。
// 坑 : 删除最后一个元素时, 伴随着卡片动画,动画消失 结束时 你才改变 currentIndex , 但是在此期间,操作过快的用户 连续点击了好几次, 那么 currentIndex 就越界了...
(2).ios版本适配
-
例1.
属性
- image.png
-
例2.
字体
iOS 9.0以后系统自带了平方字体 `PingFangSC`, 但是在iOS 9.0以前,是没有平方字体 `PingFangSC` 的, 所以注意 ~ 那些老顽固,不升级的用户, 要照顾一下哦, 要判断版本, 否则crash少不了的~
特别注意: 方正牛盲碰瓷 (尽量别使用方正字体, 可能导致赔钱、app下架等风险)
(3).字典
- 例1.
value = nil
这里iOS9以下用户手机运行如下代码时, 使用PingFangSC字体,就导致font取为nil
然后对字典操作会报错
__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]
- image.png
(3).线程
- 例1. SEGV_ACCERR报错, 一般是内存问题,在64位上比较常见,比如多线程操作某变量,堆栈非法访问等。
对于不正确的内存处理,如当程序企图访问 CPU 无法定址的内存区块时,计算机程序可能抛出 SIGSEGV。
例如:在socket 收消息中 使用dispatch_async(dispatch_queue_create
消息一多, 立马开出60多个线程,处理诸多东西, 会崩溃 会卡死, 也可能幸免~
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
dispatch_async(dispatch_queue_create("Socket message queue", NULL), ^{ // do sth};
}
解决方式:
semaphore
自己手动处理,NSOperation
,QSDispatchQueue
(内部semaphore
处理), 可设最大并发数, 否则直接上面那么用会导致无限制的创建子线程(最高60多个吧), 最终甚至抢占主线程资源, 导致卡死or崩溃~ . 解决👉GitHub Demo 参考如下
- (void)test_GCD_semaphore_WithMaxTheadCount:(NSInteger) max {
dispatch_queue_t workConcurrentQueue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t serialQueue = dispatch_queue_create("serial",DISPATCH_QUEUE_SERIAL);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(max); // create semaphore: value = 3
NSLog(@"begin: %@",[NSThread currentThread]);
for (int i = 0; i < 10; i++) {
__block int index = i;
dispatch_async(serialQueue, ^{
// If value < 0, then wait here. Else value > 0, then pass, and value -1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(workConcurrentQueue, ^{
sleep(1);
NSLog(@"执行第%zd次操作,线程:%@",index, [NSThread currentThread]);
dispatch_semaphore_signal(semaphore);}); // Perform value +1
});
}
NSLog(@"主线程...!");
// max : 2 10
// begin: 03:02:45.309 03:05:53.301
// end : 03:02:50.332 03:05:54.309
// time : ≈ 5.03s ≈ 1s
}
(二) statter列举一二
- 0.列举之间 statter小知识先预习
在ios应用中,所有的UI操作及更新都是在主线程完成,并且主线程的runloop是逐个处理用户事件的(当然其他的runloop也一样),
所以主线程必须等待上一次事件处理完成后才能继续响应下一次事件。
以上statter解释from
👉开发iOS应用如何避免卡顿
-
1.在主线程内发起耗时网络请求,主线程只能停止响应接下来的所有用户事件,等待网络请求结束。在等待的这个过程中,应用就停止响应了,也就是出现卡顿现象。
-
2.线程开太多(同上上上~)
待续~
线程管理👉github Demo
网友评论