mhillsman
mhillsman

Reputation: 770

Contact selector working in simulator but not on an actual iPhone

All my code works perfectly in the simulator. The contact picker is displayed and when a contact is pressed, it is dismissed having obtained the contact data. However, when I try this on my device, the picker is not dismissed and displays the details of the selected contact instead. From there you can press the individual properties such as numbers and addresses, but those just transfer you to the related app.

The button the user pressed to import a contact:

- (IBAction)AddContactPressed:(id)sender {
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);

if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
    ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
        // First time access has been granted, add the contact
        contactsAccessible = TRUE;
    });
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
    // The user has previously given access, add the contact
    contactsAccessible = TRUE;
}
else {
    // The user has previously denied access
    // Send an alert telling user to change privacy setting in settings app
}

//Test if contacts have been enabled or not
if (contactsAccessible) {
    //Display contact selection screen
    addressBookController = [[ABPeoplePickerNavigationController alloc] init];
    addressBookController.peoplePickerDelegate = self;
    [self presentViewController:addressBookController animated:YES completion:nil];
}
else{
    //Display text saying the contacts could not be accessed and provide a button to ask again
}
}

Here is all my code for the contact picker:

-(BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person{

//Creating dictionary to store contact info
NSMutableDictionary *contactInfoDict = [[NSMutableDictionary alloc]
                                        initWithObjects:@[@"", @"", @"", @""]
                                        forKeys:@[@"firstName", @"lastName", @"mobileNumber", @"homeNumber"]];
//First name
CFTypeRef generalCFObject;
generalCFObject = ABRecordCopyValue(person, kABPersonFirstNameProperty);
if (generalCFObject) {
    [contactInfoDict setObject:(__bridge_transfer NSString *)generalCFObject forKey:@"firstName"];
    CFRelease(generalCFObject);
}

//Last name
generalCFObject = ABRecordCopyValue(person, kABPersonLastNameProperty);
if (generalCFObject) {
    [contactInfoDict setObject:(__bridge_transfer NSString *)generalCFObject forKey:@"lastName"];
    CFRelease(generalCFObject);
}

//Phone numbers: (home and mobile)
ABMultiValueRef phonesRef = ABRecordCopyValue(person, kABPersonPhoneProperty);
for (int i=0; i < ABMultiValueGetCount(phonesRef); i++) {
    CFStringRef currentPhoneLabel = ABMultiValueCopyLabelAtIndex(phonesRef, i);
    CFStringRef currentPhoneValue = ABMultiValueCopyValueAtIndex(phonesRef, i);

    if (CFStringCompare(currentPhoneLabel, kABPersonPhoneMobileLabel, 0) == kCFCompareEqualTo) {
        [contactInfoDict setObject:(__bridge_transfer NSString *)currentPhoneValue forKey:@"mobileNumber"];
    }

    if (CFStringCompare(currentPhoneLabel, kABHomeLabel, 0) == kCFCompareEqualTo) {
        [contactInfoDict setObject:(__bridge_transfer NSString *)currentPhoneValue forKey:@"homeNumber"];
    }

    CFRelease(currentPhoneLabel);
    CFRelease(currentPhoneValue);
}
CFRelease(phonesRef);

//Getting image if contact has image
if (ABPersonHasImageData(person)) {
    NSData *contactImageData = (__bridge_transfer NSData *)ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail);

    [contactInfoDict setObject:contactImageData forKey:@"image"];        
}

//Add contact to array
if (contacts == nil) {
    contacts = [[NSMutableArray alloc] init];
}
[contacts addObject:contactInfoDict];

//Save contact
[userDefaults setObject:contacts forKey:@"Contacts"];

[self dismissViewControllerAnimated:YES completion:nil];

return NO;
}

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{

return NO;
}

-(void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker{
[self dismissViewControllerAnimated:YES completion:nil];
}

Upvotes: 1

Views: 323

Answers (2)

BootMaker
BootMaker

Reputation: 1647

The reason could be that the delegate couldn't call the delegate method. This could cause that you use different iOS on simulator and on iPhone.

My best guess that you use iOS 8 on simulator and under iOS 8 there is a new delegate method for the picker

- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person {

....// do whatever you need here

meantime the old one is what you are using.

Upvotes: 1

blazejmar
blazejmar

Reputation: 1090

From the documentation:

peoplePickerNavigationController:shouldContinueAfterSelectingPerson:property:identifier:

Return Value

YES to perform the action for the property selected and dismiss the picker.

NO to show the person in the picker.

So this is probably the issue. On simulator first method gets called while on the device the other. So you should handle picking in both methods and return YES from the one described above.

Upvotes: 0

Related Questions