[英]Data Formatters temporarily unavailable, will re-try after a 'continue'
這是我收到的錯誤消息:
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上發生-在模擬器上不發生(在模擬器上,<5個聯系人)
您尚未收到內存警告的事實並不表示它沒有發送:內存警告傳遞到主運行循環; 當您的函數仍在運行時,將不會傳遞它們。
相反,請考慮查看電話控制台(Xcode-> Organizer->您的電話->控制台,或iPCU中的等效項)。 如果它說“內存級別很關鍵”,並提到殺死您的應用程序,則說明您的內存不足。 另外,當您的內存不足時,崩潰報告器會在被殺死的進程旁邊寫入一個“低內存”崩潰日志,並帶有“ jettisoned”。 您應該在管理器中看到這些。 (由於iOS 4的“多任務處理”,后台任務也會發生拋棄。)
如果這僅是由於大量自動釋放對象引起的,則可以使用顯式自動釋放池在某種程度上緩解它:
for (int i = 0; i< [contacts count] ; i++) {
NSAutoreleasePool * pool = [NSAutoreleasePool new];
...
[pool drain]; pool = nil;
}
您的代碼還會泄漏ret
和rv
。
當您的應用程序內存不足時,會發生此錯誤。 您應該閱讀《 Apple內存管理指南》 。
我發現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;
}
第一件事是您的代碼中有內存泄漏...像這樣修復
+(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將管理隊列,以使主隊列不會被阻塞,並且您將收到內存警告。 從那時起,您必須釋放內存,並確保不要越過。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.