Reputation: 1349
I trying fill array from existing filled array but sometimes get this error:
*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[4830]
Exception caused by this code line:
NSArray *result = [NSArray arrayWithArray:self.testerLog];
testerLog is NSMutableArray and I use it for collect logs from App. tester logs filled next way:
[self.testerLog addObject:[NSString stringWithFormat:@"%@: %@ \n", [NSDate date], logRecord]];
How it could happens? No exception when I add object to testerLog and fail when trying fill array from this filled array?
Edit: About initializing testerLog. Here is code of testerLog method:
- (NSMutableArray *)testerLog {
if (!_testerLog) {
_testerLog = [NSMutableArray array];
}
return _testerLog;
}
So I think it should be not nil.
UPDATE: I forget to say that method that add NSString to testerLog may called from several threads;
Upvotes: 0
Views: 742
Reputation: 2027
The getter you posted is not thread safe. To get an equivalent thread safe getter, use the following code instead.
-(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;
}
The dispatch_once call makes sure that whatever code you put into it, it will only be executed once during you app's lifetime (in a thread-safe manner). The static onceToken
is what identifies the particular block. In your particular case this is useful because it guarantees that the array is instantiated only once no matter how many threads execute this getter.
NON-ARC ONLY: The retain is because you want the array to survive beyond this method's execution (again, ONLY if you are not using ARC).
Also, if you're not expecting to see a nil
value somewhere because it means there was some logic error: use assertions. The following is an example of how to use them:
assert(self.testerLog != nil);
NSArray *result = [NSArray arrayWithArray:self.testerLog];
Upvotes: 1
Reputation: 2187
Make sure you properly initialized your testerLog array. It's nil and that's causing your problem!
addObject may not be throwing an error because you're trying to add a valid NSString to your testerLog array. Try doing an NSLog on self.testerLog immediately after the line where you add the object, and see that it's printing the testerLog array correctly as you would expect.
Upvotes: 0