Форматирование данных временно недоступно, повторная попытка после продолжения - PullRequest
4 голосов
/ 02 октября 2010

Вот сообщение об ошибке, которое я получаю:

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 .. + Происходит только на айфоне - не симулятор (на симуляторе <5 контактов) s </p>

Ответы [ 4 ]

6 голосов
/ 02 октября 2010

Тот факт, что вы не получили предупреждение памяти, не означает, что оно не было отправлено: предупреждения памяти доставляются в основной цикл выполнения; они не будут доставлены, пока ваша функция еще работает.

Вместо этого рассмотрите возможность просмотра консоли телефона (Xcode-> Органайзер-> Ваш телефон-> Консоль или аналогичный в iPCU). Если он говорит что-то вроде «уровень памяти имеет решающее значение» и упоминает об убийстве вашего приложения, значит, у вас недостаточно памяти. Кроме того, когда вы исчерпываете память, аварийный репортер записывает журнал аварийного завершения «мало памяти» с «сброшенным» рядом с уничтоженными процессами; Вы должны увидеть это в Организаторе. (Так как в iOS 4 «многозадачность», сброс также происходит с фоновыми задачами.)

Если это связано исключительно с большой кучей автоматически выпущенных объектов, вы можете смягчить ее до некоторой степени с помощью явных пулов с автоматическим выпуском:

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

    ...

    [pool drain]; pool = nil;
}

Ваш код также пропускает ret и rv.

1 голос
/ 02 октября 2010

Эта ошибка возникает, когда вашему приложению не хватает памяти.Вам следует прочитать Руководство по управлению памятью для яблок .

0 голосов
/ 23 декабря 2011

Во-первых, у вас есть утечки памяти в вашем коде ... Исправьте это так

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

Теперь это не обязательно означает, что он создаст новый поток, однако ОС будет управлять очередью так, чтобы основная очередь не блокировалась, и вы получите предупреждение о памяти. С этого момента вы должны освободить память и убедиться, что вы не переходите.

0 голосов
/ 24 ноября 2010

Я обнаружил, что 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;
}
...