views:

260

answers:

2

Here is the error message I get:

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

Here is the code that causes this problem:

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

In the View Controller that calls the said class method, I added the following code to see if memory warnings were being sent. They are not!

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

Observations: + Found that error occurs at different points in time - sometimes at index 253, other times at 246.. + Only happens on the IPhone - not the simulator (on the simulator, there are < 5 contacts)s

+1  A: 

This error occurs when your app is running out of memory. You should read Apples Memory Management Guide.

Henrik P. Hessel
I thought so as well so I put some logging in the didReceiveMemoryWarning method of the viewcontroller that calls this class method. Unfortunately, the memory warning method is not called. So I am not sure. (updated question with the code that I had in the view controller)
amehta
didReceiveMemoryWarning is never called on the simulator (that's why there's a menu entry for it) debug your app on the device.
Henrik P. Hessel
this error is not happening on the simulator .. only on the device..and thats why I am only debugging on the device.. :)
amehta
Use instruments to check your memory/allocation usage.
Henrik P. Hessel
+2  A: 

The fact that you haven't received the memory warning doesn't mean that it wasn't sent: Memory warnings are delivered to the main run loop; they will not be delivered while your function is still running.

Instead, consider looking at the phone console (Xcode->Organizer->Your phone->Console, or the equivalent in iPCU). If it says something like "memory level is critical" and mentions killing your app, then you've run out of memory. Additionally, when you run out of memory, the crash reporter writes a "low memory" crash log with "jettisoned" beside the processes that were killed; you should see these in the Organizer. (Since iOS 4's "multitasking", jettisoning also happens to background tasks.)

If it's due solely to the large pile of autoreleased objects, you can mitigate it to some extent with explicit autorelease pools:

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

    ...

    [pool drain]; pool = nil;
}

Your code also leaks ret and rv.

tc.
That was it, Thank You. I didn't know about the "Phone Console". And I have yet to learn about memory management in Obj C. When I opened the phone console and executed this portion of the code - the messages were very clear i.e. - memory warnings galore.
amehta
I must add, however, that just by adding NSAutoreleasePool in the loop, the memory warnings or the final error did not go away. Still working on that right now.
amehta
On a hunch, you could try doing `[rv addObject:c]` instead of adding "fullContact". I'm not sure if ABRecords do any cacheing, but if they do, a cached list of everyone's phone number could be quite large...
tc.
Thanks for sharing the idea - unfortunately, I have to get the 'full contact' as I cannot see the phone numbers from just 'c'. But I will keep looking and will post the solution to this soon. Thinking of experimenting with predicates..wish there was a way to directly query the contacts db.
amehta
I meant that even if you got the "full contact", you could just add `c` to the array (code which needed the phone number later could create the "full contact" in a similar way). But `+[ABContact contactWithRecordID:]` doesn't seem to be doing anything special that isn't done by `[ABContactsHelper contacts]`; they're both wrappers around ABRecordRef, and I'm pretty sure that there's no such thing as a "full" vs "non-full" ABRecordRef. Does `[c phoneArray]` not work at all?
tc.