在使用UICollectionView -reloadItemsAtIndexPaths调试问题时,我将一个断言跟踪到一个条件,其中我(通常)需要将此方法传递给单个元素数组(我只有一个单元要重新加载)。因此,有点显而易见的是,我使用了以下等价物来生成必要的数组:
NSIndexPath *foo = ...
NSArray *bar = [NSArray arrayWithObject:foo];
[mycollectionview reloadItemsAtIndexPaths:bar];
但是,在特殊情况下,当mycollectionview仍然为空时,indexpath foo为nil(即没有要重新加载的单元格),它出现 arrayWithObject:并且出现错误:
2014-10-11 12:45:08.066 Xulu [26594:90b] *由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'* - [__ NSPlaceholderArray initWithObjects:count:]:尝试从对象[0]'
插入nil对象
然而,如果我改为使用
NSArray *bar = [NSArray arrayWithObjects:foo,nil];
一切都很好。
所以我的问题是, [NSArray arrayWithObject:nil] 是否存在错误或未记录的功能? Apple文档没有说参数必须是非零的。我看到很多关于使用 arrayWithObjects 使用nil的帖子,但没有关于 arrayWithObject 和nil的内容。这似乎是一种不常见的情况......
答案 0 :(得分:2)
根据定义,arrayWithObject
的参数必须是一个合法的指针,作为NSArray
的元素。 NSArray
不能包含nil,因此将nil传递给此方法是一个设计错误 - 因此是例外。
另一方面,arrayWithObjects
采用nil终止的参数列表。单独传递nil构成传递一个空列表,创建一个空数组。没有错。
然而,在现代的ObjC中,最好不要使用这两种方法。相反,使用数组文字:
NSArray *bar = @[foo];
这使您的意图更清晰地告知未来的代码读者,使用更清晰的错误消息捕获有问题的nil,并避免因使用arrayWithObjects
和非预期的nils而导致的静默失败。
答案 1 :(得分:1)
您不能将nil放入数组中 - 您必须存储NSNull
对象
NSArray *bar = [NSArray arrayWithObjects:foo,nil];
创建一个包含foo
的单元素数组 - nil是指示要放入数组的对象列表末尾的标记 - 它不会放入数组中
现在,如果foo
本身为零,那么这与说
NSArray *bar = [NSArray arrayWithObjects:nil,nil];
第一个nil终止列表,第二个nil被忽略 - 所以你最终得到一个空数组
NSArray *bar = [NSArray arrayWithObject:foo];
创建一个单元素数组并将指定的对象放入其中 - 但是您的对象为nil且您无法存储nil,因此您将断言失败。
答案 2 :(得分:0)
为了跟进我自己的问题,在进一步挖掘之后 - 代替上面的评论 - 这可能是按设计工作的;即一个可以说是文档错误的特征'而不是一个错误...特别是Apple的 insertObjectAtIndex:的文档明确指出:
(void)insertObject:(id)anObject atIndex:(NSUInteger)index
参数
anObject
要添加到数组内容的对象。该值不得为零。
重要提示:如果anObject为nil,则引发NSInvalidArgumentException。
arrayWithObject:文档可能会受益于类似的东西。对那些花时间作出回应的人而言。这可以关闭。