NSArrayWithObject:nil断言,但是NSArrayWithObjects:nil没有。错误或功能?

时间:2014-10-11 00:10:56

标签: ios

在使用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的内容。这似乎是一种不常见的情况......

3 个答案:

答案 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:文档可能会受益于类似的东西。对那些花时间作出回应的人而言。这可以关闭。