我尝试从现有的填充数组填充数组,但有时会出现此错误:
*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[4830]
此代码行导致异常:
NSArray *result = [NSArray arrayWithArray:self.testerLog];
testerLog是NSMutableArray,我用它来收集来自App的日志。 测试仪日志填写方式:
[self.testerLog addObject:[NSString stringWithFormat:@"%@: %@ \n", [NSDate date], logRecord]];
怎么会发生?当我将对象添加到testerLog并且在从这个填充的数组中尝试填充数组时失败时没有异常?
编辑: 关于初始化testerLog。这是testerLog方法的代码:
- (NSMutableArray *)testerLog {
if (!_testerLog) {
_testerLog = [NSMutableArray array];
}
return _testerLog;
}
所以我认为应该不是零。
更新 我忘了说可以从几个线程中调用添加NSString到testerLog的方法;
答案 0 :(得分:1)
您发布的getter不是线程安全的。要获得等效的线程安全getter,请改用以下代码。
-(NSMutableArray *)testerLog {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// If you're not using ARC you most definitely want to retain the array!
// _testerLog = [[NSMutableArray array] retain];
// If you're using ARC you should just assign
_testerLog = [NSMutableArray array];
});
return _testerLog;
}
dispatch_once调用确保无论你输入什么代码,它都只会在你的应用程序生命周期内执行一次(以线程安全的方式)。静态onceToken
是标识特定块的内容。在您的特定情况下,这很有用,因为无论执行此getter的线程数是多少,它都可以保证数组只被实例化一次。
仅限NON-ARC:保留是因为您希望阵列在此方法执行之后存活(再次,仅在您不使用ARC时)。
此外,如果您不希望在某处看到nil
值,因为这意味着存在一些逻辑错误:使用断言。以下是如何使用它们的示例:
assert(self.testerLog != nil);
NSArray *result = [NSArray arrayWithArray:self.testerLog];
答案 1 :(得分:0)
确保正确初始化了testerLog阵列。这是零,这导致了你的问题!
addObject可能不会引发错误,因为您尝试将有效的NSString添加到testerLog数组中。尝试在添加对象的行之后立即在self.testerLog上执行NSLog,并看到它正如您期望的那样正确打印testerLog数组。