简体   繁体   中英

Optimize Objective C code to access contacts

I have some code to copy contacts from Addreesbook. It works perfectly if there is a small number of contacts. Now In my phone there us 1200 contacts and the app crashes when I tried to copy them. Can anyone help me to optimize this code or rewrite code? The code I am using is added below:

ABAddressBookRef addressBook = ABAddressBookCreate();
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
    CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);

    NSString *requestContactsString = @"<contacts>";    


    for (int i=0; i<nPeople; i++)
    {
        NSLog(@"Started : %d", i);

        ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
        CFTypeRef firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
        CFTypeRef lastName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
        CFTypeRef email = ABRecordCopyValue(ref, kABPersonEmailProperty);
        CFTypeRef phone = ABRecordCopyValue(ref, kABPersonPhoneProperty);

        requestContactsString = [requestContactsString stringByAppendingFormat:@"<item>"];

        if(firstName)
        {
            requestContactsString = [requestContactsString stringByAppendingFormat:@"<firstname>%@</firstname>", firstName];
            CFRelease(firstName);
            firstName = nil;
        }
        if(lastName)
        {
            requestContactsString = [requestContactsString stringByAppendingFormat:@"<lastname>%@</lastname>", lastName];
            CFRelease(lastName);
            lastName = nil;
        }
        if(email)
        {
            if(ABMultiValueGetCount(email)>0)
            {
                CFTypeRef em = ABMultiValueCopyValueAtIndex(email, 0);
                requestContactsString = [requestContactsString stringByAppendingFormat:@"<email>%@</email>", em];
                CFRelease(em);
            }
            CFRelease(email);
            email = nil;
        }
        if(phone)
        {
            if(ABMultiValueGetCount(phone)>0)
            {
                CFTypeRef ph = ABMultiValueCopyValueAtIndex(phone, 0);
                requestContactsString = [requestContactsString stringByAppendingFormat:@"<phone>%@</phone>", ph];
                CFRelease(ph);
            }
            CFRelease(phone);
            phone = nil;
        }

        requestContactsString = [requestContactsString stringByAppendingFormat:@"</item>"];
    }


    if(allPeople)
    {
        CFRelease(allPeople);
        allPeople = nil;
    }
    if(addressBook)
    {
        CFRelease(addressBook);
        addressBook = nil;
    }

    requestContactsString = [requestContactsString stringByAppendingFormat:@"</contacts>"];

    NSString *hashedContactsString = [self generateHashedPassword:requestContactsString];

The major inefficiency I can see is the use of [NSString stringByAppendingFormat] which is creating a new NSString object each time it's called. This means that you have a large number of long auto-released NSString objects that are no longer being used until the next run loop (unless you are using ARC, in which case the situation is probably better).

I think you would make much better use of memory, and get better performance, by making requestContactsString an NSMutableString and using [NSMutableString appendString] ( reference ) instead. This would modify the existing object, allocating more memory to accept the new string.

Each append would look like this:

[requestContactsString appendString:[NSString stringWithFormat:@"<lastname>%@</lastname>", lastName]];

Which still creates a large number of auto-released objects, but they are much smaller.

Use a NSMutableString and build your XML with the appendFormat: method. In your loop you are copying the whole string you've assembled so far multiple times.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM