-3

I'm running this code in order to create an image contains the caller's name, and setting it to the specific contact, but while it runs, I get Received memory warning and it crashes...

-(void)RunActionInBlack{


//black bg - white text

ABAddressBookRef addressBook;
CFErrorRef error = NULL;

addressBook = ABAddressBookCreate();

CFArrayRef array=ABAddressBookCopyArrayOfAllPeople(addressBook);

ABRecordRef person;
int len=CFArrayGetCount(array);

for (int i = 0; i<len; i++){
    person = CFArrayGetValueAtIndex(array, i);
     details.text = [NSString stringWithFormat:@"Done. %d of %d contacts", i+1,len];
    [act stopAnimating];
    NSString *firstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
    NSString *lastName = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);

    if (firstName == NULL) {
        firstName = @"";
    }
    if (lastName == NULL ) {
        lastName = @"";
    }

    UIImage *im = [self addText:[UIImage imageNamed:@"black.png"] andText:[NSString stringWithFormat:@"%@ %@",firstName, lastName]];
    NSData *dataRef = UIImagePNGRepresentation(im);

    ABPersonSetImageData(person, (CFDataRef)dataRef, &error);


    [lastName release];
    [firstName release];
    [dataRef release];
    CFRelease(dataRef);
    [im release];
}
ABAddressBookSave(addressBook, &error);
CFRelease(array);
CFRelease(addressBook);
}

Creating the text:

-(UIImage *)addText:(UIImage *)img andText:(NSString*)txt{

UIImageView *imView =[[UIImageView alloc] initWithImage:img ];
UIView *tempView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, img.size.width, img.size.height)];
[tempView addSubview:imView];

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, -100, img.size.width, img.size.height)];
[label setText:txt];
[label setFont:[UIFont boldSystemFontOfSize:160]];
[label setTextColor:[UIColor whiteColor]];
[label setTextAlignment:UITextAlignmentCenter];
[label setBackgroundColor:[UIColor clearColor]];
[label setNumberOfLines:10];
[tempView addSubview:label];

UIGraphicsBeginImageContext(tempView.bounds.size);
[tempView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[label release];
[tempView release];
[imView release];
return finalImage;
}

I don't have any memory leaks or something...

I'm running those methods like: [self performSelectorInBackground:@selector(RunActionInWhite) withObject:nil];

Thanks in advance.

Yosi Dahan
  • 441
  • 6
  • 19
  • 1
    it seem the memory management is a bit poor in this code. the bridging is a massive chaos between the `CF` references and the Objective C objects... e.g. the `dataRef` is **not** `CF` reference, the `firstName` and `lastName` **are** `CF` references. these tiny things can cause serious memory leak. – holex Feb 16 '13 at 20:50

2 Answers2

2

If you're iterating through a large array and get a memory warning, you are probably using resources that aren't getting released until after you exit the for loop. (Or in this case, not getting released at all, because your app crashes.)

You would want to wrap the code inside your loop with

for (int i=0; i<max; i++) {
    @autoreleasepool {

    }
}
buildsucceeded
  • 4,203
  • 4
  • 34
  • 72
0

Seems like you're running out of memory while keeping a lot of objects which cannot be released, like the addressBook contents, and also you seem to have a whole copy of addressBook called array.

So,

  • Do you really need that copy of the addressBook? Try getting rid of it.
  • Split the iteration into smaller parts, save address book after each chunk of few tens of records, that should free up some internally used resources.

Next, you can try profiling your allocations using Instruments and see what takes most of the memory.

coverback
  • 4,413
  • 1
  • 19
  • 31