常见的线上异常崩溃一

21 篇文章 0 订阅

一.UITableView reloadData的崩溃:

[tableView reloadData]后当需要立即获取tableview的cell、高度,或者需要滚动tableview,那么直接在reloadData后执行代码是会有问题的。(如 在项目中用到scrollToRowAtIndexPath,但程序一旦调用scrollToRowAtIndexPath就出错,经分析是数据源和tableview中cell不同步的原因, 比如,dataArray中有3个元素,而tableview中只显示了2个元素,当你scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:2 时当然就出错了)

原因:

因为[tableview reloaddata] 需要在当前方法在runloop中执行完后它再在runloop中执行,处理函数是在runloop中串行的排队执行的。但是[tableview reloaddata]后面的代码需要[tableview reloaddata]的计算结果,所以[tableview reloaddata]后面的代码需要一个延迟执行。只有当前方法不再占用runloop,[tableview reloaddata]才可以在runloop中执行,而这时延迟执行的部分在runloop中早就排在了[tableview reloaddata]的前面执行完了。如果表中的数据非常大,在一个runloop周期没执行完,这时需要tableview视图数据的操作就会出问题了。

解决方法:(就是要等排队,等tableview的刷新操作完成,再去做滚动等其他操作)

方法1:layoutIfNeeded会强制重绘并等待完成

[self.tableView reloadData];  

[self.tableView layoutIfNeeded];  

方法2:

reloadData会在主队列执行,而dispatch_get_main_queue会等待机会,直到主队列空闲才执行。

[self.collectionView reloadData];

dispatch_async(dispatch_get_main_queue(), ^{

// 刷新完成   

 [self.tableView setContentOffset:offset animated:NO];

    });

}

方法3:

- (void)reload

{

    [_tableView reloadData];

    [self performSelector:@selector(scrollToIndexPath:) withObject:[NSIndexPath indexPathForRow:rowIndex inSection:sectionIndexafterDelay:0.0];

}

- (void)scrollToIndexPath:(NSIndexPath *)path

{

    [_tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionTop animated:YES];

}

 

二.

UILocalNotification *localNoti = [[UILocalNotification alloc] init];

localNoti.alertTitle = @"通知"; 

 这个本地通知在iOS8.2以下系统会崩溃,因为alertTitle是8.2才有的属性.这里只要判断一下系统版本就可以。

 

三.BOOL 若干陷阱

1.变量BOOL未初始化时,出现随机值(但是当一个对象的属性含有bool类型时,如果对象用init方法初始化,则它的bool属性是nil)

如果你声明了一个变量但是没有为它提供一个值,它就被认为是“未初始化的”。C中一个未初始化的变量具有“未定义”值,通常是垃圾,包含最后一次写入该地址时发生的任何事情。严格来说,“未定义”意味着你不应该使用该值。

这个变量是本地的,每次运行该方法时都会被重新创建,因此会得到一个新的实际值,但每次都是未定义值。

在ARC下,本地对象指针总是有一个默认值nil,但是类似BOOL的非对象类型的局部变量仍然被初始化为垃圾,垃圾值就是未确定的值,即会出现随机值。

解决:给变量赋默认值。

2.将普通整形转换成 BOOL 时要小心。不要直接将 BOOL 值与 YES 进行比较。

Ojbective-C 中把 BOOL 定义成无符号字符型,这意味着 BOOL 类型的值远不止 YES``(1)或 ``NO``(0)。不要直接把整形转换成 ``BOOL。常见的错误包括将数组的大小、指针值及位运算的结果直接转换成 BOOL ,取决于整型结果的最后一个字节,很可能会产生一个 NO 值。当转换整形至 BOOL 时,使用三目操作符来返回 YES 或者 NO。(译者注:读者可以试一下任意的 256 的整数的转换结果,如 256、512 …)

OC中用一个字节,即8位来表示BOOL值,也就是取一个数的低八位。那么对于8960这个数,它明显是非零数字,但是,但是!它的低八位都是零,所以它是NO。

列:

int a = 8960;

if (a) { ISLog(@"---1---"); }

 else { ISLog(@"---2---"); }

// 这种方式很坑的。注意底部数据的打印

if (a == YES) { ISLog(@"---3---"); }

else { ISLog(@"---4---"); }

 BOOL b = a;

 if (b) { ISLog(@"---5---"); }

else { ISLog(@"---6---"); }

 if (b == YES) { ISLog(@"---7---"); }

else { ISLog(@"---8---"); }

 2018-06-08 16:28:51.143529+0800 ISBaseDemo[27344:15315162] -[ISHomePageViewController buttonClick:] [Line 119] ---1---

2018-06-08 16:28:51.143617+0800 ISBaseDemo[27344:15315162] -[ISHomePageViewController buttonClick:] [Line 127] ---4---

2018-06-08 16:28:51.143632+0800 ISBaseDemo[27344:15315162] -[ISHomePageViewController buttonClick:] [Line 131] ---5---

2018-06-08 16:28:51.143643+0800 ISBaseDemo[27344:15315162] -[ISHomePageViewController buttonClick:] [Line 137] ---7---

你可以安全在 BOOL、_Bool 以及 bool 之间转换(参见 C++ Std 4.7.4, 4.12 以及 C99 Std 6.3.1.2)。你不能安全在 BOOL 以及 Boolean 之间转换,因此请把 Boolean 当作一个普通整形,就像之前讨论的那样。但 Objective-C 的方法标识符中,只使用 BOOL。

对 BOOL 使用逻辑运算符(&&,|| 和 !)是合法的,返回值也可以安全地转换成 BOOL,不需要使用三目操作符。

错误的用法:

- (BOOL)isBold {

  return [self fontTraits] & NSFontBoldTrait;}

- (BOOL)isValid {

  return [self stringValue];}

正确的用法:

(BOOL)isBold {

 return ([self fontTraits] & NSFontBoldTrait) ? YES : NO;

}

 - (BOOL)isValid {

return [self stringValue] != nil;

}

- (BOOL)isEnabled {

return [self isValid] && [self isBold];

}

同样,不要直接比较 YES/NO 和 BOOL 变量。不仅仅因为影响可读性,更重要的是结果可能与你想的不同。

错误的用法:

BOOL great = [foo isGreat];

if (great == YES)

  // ...be great!

正确的用法:

BOOL great = [foo isGreat];

if (great)

  // ...be great!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值