简体   繁体   中英

Fetching array of contacts from ABAddressBookRequestAccessWithCompletion() gives nil

I am trying to print out all of my phone's contacts to the console, using NSLog() . Currently this code is just printing (null) .

.h

@property (nonatomic, strong) NSMutableArray *contactsObjects;

.m

@synthesize contactsObjects;
//lazy instantiation. 
- (NSMutableArray *)contactsObjects
{
    if(!contactsObjects)
    {
        contactsObjects = [[NSMutableArray alloc]init];
    }

    return contactsObjects;
}

- (void)viewWillAppear:(BOOL)animated
{
    CFErrorRef error = nil;

    // Request authorization to Address Book
    ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, &error);

    if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
        ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
            if (granted) {
                // First time access has been granted, add all the user's contacts to array.
                CFMutableArrayRef contactsObjects = ABAddressBookCopyArrayOfAllPeople(addressBookRef);
            } else {
                // User denied access.
                // Display an alert telling user that they must allow access to proceed to the "invites" page.
            }
        });
    }
    else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
        // The user has previously given access, add all the user's contacts to array.
        CFMutableArrayRef contactsObjects = ABAddressBookCopyArrayOfAllPeople(addressBookRef);
    }
    else {
        // The user has previously denied access
        // Send an alert telling user that they must allow access to proceed to the "invites" page.
    }

    NSLog(@"%@", contactsObjects);
}

I get two warnings here:

在此处输入图片说明

I have no idea what I am supposed to do in order to properly print the names and numbers of my contacts to the console.

How do I print my contacts names and numbers?

You say it prints out null and that you get an error. But this would explain your error.

contactObjects is defined within the if block and the else if block. So by the time you are outside of your conditional it's no longer defined.

Try this

- (void)viewWillAppear:(BOOL)animated
{
    CFErrorRef error = nil;

    // Request authorization to Address Book
    ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, &error);

    if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
        ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
            if (granted) {
                // First time access has been granted, add all the user's contacts to array.
                contactsObjects = ABAddressBookCopyArrayOfAllPeople(addressBookRef);
            } else {
                // User denied access.
                // Display an alert telling user that they must allow access to proceed to the "invites" page.
            }
        });
    }
    else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
        // The user has previously given access, add all the user's contacts to array.
        contactsObjects = ABAddressBookCopyArrayOfAllPeople(addressBookRef);
    }
    else {
        // The user has previously denied access
        // Send an alert telling user that they must allow access to proceed to the "invites" page.
    }

    NSLog(@"%@", contactsObjects);
}

You have a scope problem with your code. The contactsObjects variables in viewWillAppear: are not related to the ivar you have called contactsObjects . You're declaring new variables that are using the same name. The NSLog() at the end, on the other hand, is the ivar. But setting those other variables didn't put anything into the ivar, so you see (null) , which is how NSLog() represents "no object".

Fix this by not making new variable declarations, but using the ivar.

if (granted) {
    contactsObjects = ABAddressBookCopyArrayOfAllPeople(addressBookRef);

else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
    contactsObjects = ABAddressBookCopyArrayOfAllPeople(addressBookRef);

You will also need to cast these:

    contactsObjects = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBookRef);

(Also, the function doesn't return a mutable array, so you may have trouble down the road with that.)

The second problem is that ABAddressBookRequestAccessWithCompletion() doesn't stop and wait for its completion Block to run. While access is being requested, the rest of your method carries on, so you reach the NSLog() before contactsObjects is actually set in that case.

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