以下是我收到的错误消息:
ContactsWithPN - start loop
Program received signal: “0”.
Data Formatters temporarily unavailable, will re-try after a 'continue'. (Unknown error loading shared library "/Developer/usr/lib/libXcodeDebuggerSupport.dylib")
以下是导致此问题的代码:
+(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];
return ret;
}
在调用所述类方法的View Controller中,我添加了以下代码以查看是否正在发送内存警告。他们不是!
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
NSLog(@"InviteFriends - memory warning received");
}
观察: +发现错误发生在不同的时间点 - 有时在索引253,其他时间在246 .. +只发生在iPhone上 - 而不是模拟器(在模拟器上,有&lt; 5个联系人)s
答案 0 :(得分:6)
您没有收到内存警告这一事实并不意味着它没有被发送:内存警告被传送到主运行循环;当你的功能仍在运行时,它们将无法发送。
相反,请考虑查看电话控制台(Xcode-&gt; Organizer-&gt;您的手机 - &gt;控制台,或iPCU中的等效控制台)。如果它说“内存级别至关重要”并且提到杀死你的应用程序,那么你的内存已经耗尽。此外,当你的内存不足时,崩溃记者会在被杀死的进程旁边写一个“低内存”崩溃日志并“抛弃”;你应该在组织者中看到这些。 (自从iOS 4的“多任务处理”以来,抛弃也会发生在后台任务中。)
如果它只是由于大量自动释放的对象,你可以在一定程度上使用显式的自动释放池来缓解它:
for (int i = 0; i< [contacts count] ; i++) {
NSAutoreleasePool * pool = [NSAutoreleasePool new];
...
[pool drain]; pool = nil;
}
您的代码也会泄漏ret
和rv
。
答案 1 :(得分:1)
当您的应用内存不足时,会发生此错误。你应该阅读Apples Memory Management Guide。
答案 2 :(得分:0)
我发现ABContact也会泄漏内存,请参阅下面ABContactHelper代码的一部分。
+ (NSArray *) contacts
{
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *thePeople = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
NSMutableArray *array = [NSMutableArray arrayWithCapacity:thePeople.count];
for (id person in thePeople)
{
[array addObject:[ABContact contactWithRecord:(ABRecordRef)person]];
}
[thePeople release];
//I think need CFRelease(addressBook); here
return array;
}
答案 3 :(得分:0)
首先,您的代码中存在内存泄漏...修复此问题
+(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);
现在这并不意味着它会创建一个新线程,但是os将管理队列,以便主队列不会被阻塞,你将收到内存警告。从那时起,你必须释放记忆,并确保你不要过去。