代码之家  ›  专栏  ›  技术社区  ›  amehta

数据格式化程序暂时不可用,将在“继续”后重试

  •  4
  • amehta  · 技术社区  · 15 年前

    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;
    }
    

    在调用上述类方法的视图控制器中,我添加了以下代码以查看是否发送了内存警告。他们不是!

    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        NSLog(@"InviteFriends - memory warning received");
    }
    

    观察: +发现错误发生在不同的时间点——有时在索引253处,有时在索引246处。。 +只发生在IPhone上-不发生在模拟器上(在模拟器上,有<5个联系人)

    4 回复  |  直到 12 年前
        1
  •  6
  •   tc.    15 年前

    相反,可以考虑查看电话控制台(Xcode->Organizer->Your phone->console,或iPCU中的等效控制台)。如果它说“内存级别很关键”之类的话,并提到要关闭你的应用程序,那么你的内存就用完了。此外,当内存不足时,crash reporter会在被终止的进程旁边写一个“内存不足”的崩溃日志,并带有“丢弃”字样;您应该在管理器中看到这些内容。(由于iOS4的“多任务”功能,抛弃也会发生在后台任务上。)

    for (int i = 0; i< [contacts count] ; i++) {
        NSAutoreleasePool * pool = [NSAutoreleasePool new];
    
        ...
    
        [pool drain]; pool = nil;
    }
    

    你的代码也会泄露 ret rv .

        2
  •  1
  •   Henrik P. Hessel    15 年前

    当应用程序内存不足时会发生此错误。你应该读书 Apples Memory Management Guide

        3
  •  0
  •   fzaziz Danish    14 年前

    第一件事是你的代码有内存泄漏。。。像这样修理

    +(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那样对你产生影响。他说。所以简单的答案是主运行回路堵塞了。你可以做的是在一个单独的线程中执行这个操作,以确保主循环没有阻塞。。。如果你在iOS4+上,你可以通过

    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);
    

    现在这不一定意味着它将创建一个新线程,但是操作系统将管理队列,这样主队列就不会被阻塞,并且您将收到内存警告。从那时起,你必须释放记忆,并确保你不去了。

        4
  •  0
  •   Sviatoslav Yakymiv    10 年前

    我发现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;
    }