Во-первых, у вас есть утечки памяти в вашем коде ... Исправьте это так
+(NSArray *) contactsWithPhoneNumbers{
NSArray *contacts = [ABContactsHelper contacts];
NSMutableArray *rv = [[NSMutableArray alloc] init];
NSLog(@"ContactsWithPN - start loop");
for (int i = 0; i< [contacts count] ; i++) {
ABContact * c = (ABContact*)[contacts objectAtIndex:i];
ABContact * fullContact = [ABContact contactWithRecordID:[c recordID]];
if ([[fullContact phoneArray] count] > 0) {
[rv addObject:fullContact];
}
}
NSLog(@"ContactsWithPN - end loop");
NSArray *ret = [[NSArray alloc] initWithArray:rv];
//You need to release rv since you dont need it any more as you have copied the contents to a new array ( this itself is a waste ) so you must release the old array
[rv release];
//Now when you return the array you must still not hold object ownership since the function dies after returning so you give it a delayed release which kicks in when the autorelease is flushed.
return [ret autorelease];
}
Обычно автоматический выпуск сбрасывается в определенное время по решению ОС, однако вы можете создать свой собственный пул, чтобы не тратить ресурсы. Так что в идеале вы будете звонить вот так
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *contactArray = [[self contactsWithPhoneNumbers] retain];
[pool drain];
//This will release the object ownership held by the function
Наконец, вы делаете все это, и у вас нет утечек памяти, но вы все равно получаете эту ошибку. Ответ, потому что предупреждение о памяти не дошло до вас как @tc. сказал. Поэтому простой ответ заключается в том, что основной цикл выполнения был засорен. Что вы можете сделать, это, возможно, сделать эту операцию в отдельном потоке, чтобы убедиться, что основной цикл не засорен ... Если вы работаете на iOS 4+, вы можете сделать это легко с помощью
dispatch_queue_t otherQueue = dispatch_queue_create("com.company.otherqueue", NULL);
dispatch_async(otherQueue, ^{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *contactArray = [[self contactsWithPhoneNumbers] retain];
[pool drain];
}
dispatch_release(otherQueue);
Теперь это не обязательно означает, что он создаст новый поток, однако ОС будет управлять очередью так, чтобы основная очередь не блокировалась, и вы получите предупреждение о памяти. С этого момента вы должны освободить память и убедиться, что вы не переходите.