0

我正在使用此函数访问联系人列表并使用 MContact 类保存联系人对象,但是此代码给了我一些内存泄漏,我无法弄清楚。请帮助!

 +(NSArray *)getAllContacts

{

    CFErrorRef *error = nil;


    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);

    __block BOOL accessGranted = NO;
    if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);
        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
            accessGranted = granted;
            dispatch_semaphore_signal(sema);
        });
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

    }
    else { // we're on iOS 5 or older
        accessGranted = YES;
    }

    if (accessGranted) {

#ifdef DEBUG
        NSLog(@"Fetching contact info ----> ");
#endif


        ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
        ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
        CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName);
        CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
        NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];


        for (int i = 0; i < nPeople; i++)
        {
            MContact *contacts = [MContact new];

            ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);

            //get First Name and Last Name

            contacts.firstName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);

            contacts.lastName =  (__bridge NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);

            if (!contacts.firstName) {
                contacts.firstName = @"";
            }
            if (!contacts.lastName) {
                contacts.lastName = @"";
            }


            NSMutableArray *contactEmails = [NSMutableArray new];
            ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty);

            for (CFIndex i=0; i<ABMultiValueGetCount(multiEmails); i++) {
                CFStringRef contactEmailRef = ABMultiValueCopyValueAtIndex(multiEmails, i);
                NSString *contactEmail = (__bridge NSString *)contactEmailRef;

                [contactEmails addObject:contactEmail];
                // NSLog(@"All emails are:%@", contactEmails);

            }

            if([contactEmails count]==0){
                return items ;
            }
            else{
                [contacts setemails:contactEmails];
                [items addObject:contacts];

            }




#ifdef DEBUG
    #endif




        }
        CFRelease(addressBook);
        return items;



    } else {
#ifdef DEBUG
        NSLog(@"Cannot fetch Contacts :( ");        
#endif
        return NO;


    }


}
4

1 回答 1

1

这里需要注意的是,按照惯例,“复制”的函数返回具有递增引用计数的对象,就像“创建”的函数一样。因此,按照您 CFRleased 的方式addressBook,您也需要对复制的对象执行此操作。或者,当您将 CFObjects 桥接到 NSObjects 时,a__bridge_transfer会将所有权传递给 ARC,因此 ARC 可以为您释放它。

这里的另一个问题是函数中的多个返回点。如果这是您想要做的,您需要确保在每个return.

希望我在这里抓住了一切:

+ (NSArray *)getAllContacts
{
    CFErrorRef *error = nil;

    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);

    __block BOOL accessGranted = NO;
    if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);
        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
            accessGranted = granted;
            dispatch_semaphore_signal(sema);
        });
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    }
    else { // we're on iOS 5 or older
        accessGranted = YES;
    }

    if (accessGranted) {

#ifdef DEBUG
        NSLog(@"Fetching contact info ----> ");
#endif


        //ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error); Removing this line as you have this already. If you need to recreate, you must release the first one.
        ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
        CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName);
        CFRelease(source); // Copied object, so release.
        CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
        NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];

        for (int i = 0; i < nPeople; i++)
        {
            MContact *contacts = [MContact new];

            ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);

            //get First Name and Last Name

            contacts.firstName = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);

            contacts.lastName =  (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);

            if (!contacts.firstName) {
                contacts.firstName = @"";
            }
            if (!contacts.lastName) {
                contacts.lastName = @"";
            }

            NSMutableArray *contactEmails = [NSMutableArray new];
            ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty);

            for (CFIndex i=0; i<ABMultiValueGetCount(multiEmails); i++) {
                CFStringRef contactEmailRef = ABMultiValueCopyValueAtIndex(multiEmails, i);
                NSString *contactEmail = (__bridge_transfer NSString *)contactEmailRef;

                [contactEmails addObject:contactEmail];
                // NSLog(@"All emails are:%@", contactEmails);

            }
            CFRelease(multiEmails);                

            if([contactEmails count]==0) {
                break; 
                // If we return here, we'll leak addressBook and allPeople
                // We could release both, then return.
            }
            else {
                [contacts setemails:contactEmails];
                [items addObject:contacts];
            }


#ifdef DEBUG
    #endif

        }
        CFRelease(addressBook);
        CFRelease(allPeople); // Copied, so must release
        return items;



    } else {
#ifdef DEBUG
        NSLog(@"Cannot fetch Contacts :( ");        
#endif
        CFRelease(addressBook);
        return nil;


    }
}
于 2014-02-20T12:14:39.063 回答