NSArray从数组填充尝试插入nil对象

时间:2013-01-18 06:52:50

标签: ios nsarray

我尝试从现有的填充数组填充数组,但有时会出现此错误:

*** -[__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的方法;

2 个答案:

答案 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数组。