我收到NSInvalidArgumentException
我的代码中第1148行的Crashlytcs发现*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil
异常,向您显示我的代码的1147-1149行:
if(snapshot.stickerInfoForAnalitycs) {
[self.usedStickers addObject:snapshot.stickerInfoForAnalitycs];//1148 line
}
self.usedStickers
是NSMutableArray
这怎么可能? (我知道crashlitycs有可能显示错误的行,但这不太可能,因为这个崩溃出现在应用程序的9.20版本中,而在9.24版本中它仍然在1148行中。)
UPD:stickerInfoForAnalitycs是一个NSString *属性,没有getter / setter覆盖。声明为@property (nonatomic) NSString * stickerInfoForAnalitycs;
答案 0 :(得分:1)
根据您提供的代码段,在snapshot.stickerInfoForAnalitycs
添加nil
之前,您确保NSMutableArray
不是-[__NSArrayM insertObject:atIndex:]
。
错误消息self.usedStickers
清楚地表明nil
不是__NSArrayM
,实际上是NSMutableArray
的实例,它是snapshot.stickerInfoForAnalitycs
类的私有子类簇。这是正常的。
所以,我可以提出最有可能发生问题的情况 - 另一个线程在if
语句中测试后立即修改stickerInfoForAnalytics
值,但在插入之前数组。
因此,我建议检查其他线程是否不会修改stickerInfoForAnalitycs
值。使用启用的线程清理程序运行代码可能会有所帮助。有关详细信息,请参阅https://developer.apple.com/documentation/code_diagnostics/thread_sanitizer/enabling_the_thread_sanitizer。请注意,线程清理程序是一个非常好的工具,但它仍然无法检测到每个可能的问题。因此,您仍然需要阅读代码并查找stickerInfoForAnalitycs
值已更改的所有位置。
另一种可能性是,例如,nil
方法的自定义实现可能会在首次访问时返回正确的值,但在第二次访问时会返回{{1}}。我认为这个选项不太可能。
答案 1 :(得分:0)
访问属性时,最好将一个值赋给局部变量,以确保在检查属性和使用它的时间之间不会发生变异。或者,您可以使用@synchronized
块来确保属性的所有访问都是互斥的。
从根本上说,你假设价值不可能是nil
是错误的,因为你得到了两次不同的价值。
NSString *stickerInfoForAnalitycs = snapshot.stickerInfoForAnalitycs;
if (stickerInfoForAnalitycs != nil) {
[self.usedStickers addObject:stickerInfoForAnalitycs];//1148 line
}
使用此代码,实际上无法获得NSInvalidArgumentException
。
答案 2 :(得分:-4)
你不妨试试这个:
if(snapshot.stickerInfoForAnalitycs) {
@synchronized(self.usedStickers) {
[self.usedStickers addObject:snapshot.stickerInfoForAnalitycs];//1148 line
}
}