ios/c/addressbook: Parse kABPersonAddressProperty crash - ios

I am using the following code to retrieve different address fields from the Addressbook. It works okay for name and some properties but crashes with address. I suspect that the address is an int rather than string but can't find anything in the docs to explain why it should be different. Would appreciate any suggestions:
//This works:
CFStringRef jobtitleRef = nil;
jobtitleRef = ABRecordCopyValue(addressBookRecord, kABPersonJobTitleProperty);
NSString *jobtitle = #"";
if (jobtitleRef!=nil) {
jobtitle =[jobtitle stringByAppendingString:(__bridge NSString *)jobtitleRef];
}
//But this crashes
CFStringRef addr1Ref = nil;
addr1Ref = ABRecordCopyValue(addressBookRecord, kABPersonAddressProperty);
NSString *addr1 = #"";
if (addr1Ref!=nil) {
addr1 = [addr1 stringByAppendingString:(__bridge NSString *)addr1Ref]; //crashes on this line
}
Edit:
Found the answer in another question:
ABMultiValueRef st = ABRecordCopyValue(person, kABPersonAddressProperty);
if (ABMultiValueGetCount(st) > 0) {
CFDictionaryRef dict = ABMultiValueCopyValueAtIndex(st, 0);
self.street.text = CFDictionaryGetValue(dict, kABPersonAddressStreetKey);
}

Related

How to check if a contact in Address Book has multiple numbers in iOS?

I have a requirement to determine if a contact that is saved in the address book has multiple mobile numbers.
I have the record ID of a Contact and I need to check if that contact has multiple mobile numbers.
Is this possible?
Got the Answer!!! I have written a method to get the total count of mobile numbers for a contact
-(NSInteger)getCountOfTotalMobileNumbersForContact:(ContactData *)contactData{
NSInteger totalCountOfMobileNumbers = 0;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
ABRecordRef contact = ABAddressBookGetPersonWithRecordID(addressBook, (int)contactData.mRecordID);
if(contact != nil)
{
self.phoneNumbers = ABRecordCopyValue(contact, kABPersonPhoneProperty);
NSString *lFirstName = (__bridge_transfer NSString*)ABRecordCopyValue(contact, kABPersonFirstNameProperty);
NSString *lLastName = (__bridge_transfer NSString*)ABRecordCopyValue(contact, kABPersonLastNameProperty);
NSString *fullName = lFirstName;
if (lLastName.length) {
fullName = [[lFirstName stringByAppendingString:#" "] stringByAppendingString:lLastName];
}
totalCountOfMobileNumbers = ABMultiValueGetCount(self.phoneNumbers);
}
return totalCountOfMobileNumbers;
}

Swift : Issue with accessing CFDictionaryRef for ABAddressBookRef

I'v collected contact's address information in ObjC as,
ABMultiValueRef addressProperty = ABRecordCopyValue(contactRef, kABPersonAddressProperty);
CFDictionaryRef dict = ABMultiValueCopyValueAtIndex(addressProperty, 0);
if(dict)
{
NSString *street = (NSString *)CFDictionaryGetValue(dict, kABPersonAddressStreetKey);
}
So, equivalent Swift code would be,
let addressProperty : ABMultiValueRef = ABRecordCopyValue(contactRef, kABPersonAddressProperty).takeUnretainedValue() as ABMultiValueRef
if let dict : CFDictionaryRef = ABMultiValueCopyValueAtIndex(addressProperty, 0).takeUnretainedValue() as? CFDictionaryRef
{
let street = CFDictionaryGetValue(dict,kABPersonAddressStreetKey)
// Stuck here, among CFString!, UnsafePointer<Void>, CFDictionaryRef ...
}
How will I fetch street and other similar information?
Can you use NSDictionary instead? (not tested)
if let dict : NSDictionary = ABMultiValueCopyValueAtIndex(addressProperty, 0).takeUnretainedValue() as? NSDictionary
{
let street = dict[kABPersonAddressStreetKey]
}

How do I get Facebook and custom social addresses from iOS address book?

In my peoplePickerNavigationController:shouldContinueAfterSelectingPerson I'm able to read a bunch of the iOS Contacts info from the chosen contact into my app.
The one item I can't figure out how to read is the Facebook (and other social) address info. Here's what I've got and I know it's not quite right. The problem has something to do with the label I think:
ABMultiValueRef socialRef = ABRecordCopyValue(person, kABPersonSocialProfileProperty);
for (int i = 0; i < ABMultiValueGetCount(socialRef); i++) {
CFStringRef currentSocialLabel = ABMultiValueCopyLabelAtIndex(socialRef, i);
CFStringRef currentSocialValue = ABMultiValueCopyValueAtIndex(socialRef, i);
if (CFStringCompare(currentSocialLabel, kABPersonSocialProfileServiceFacebook, 0) == kCFCompareEqualTo) {
[theContactInfoDictionary setObject:(__bridge NSString *)currentSocialValue forKey:#"theFacebook"];
}
CFRelease(currentSocialLabel);
CFRelease(currentSocialValue);
}
CFRelease(socialRef);
Please point me in the right direction.
Furthermore, I also need to check if there is a custom social entry for "Google+" (my app can create these entries in another place) and if there is, I want to import that value as well. How do I go about doing this?
Thanks!
sigh
And I figured it out. Here's what I did:
ABMultiValueRef socialRef = ABRecordCopyValue(person, kABPersonSocialProfileProperty);
for (int i = 0; i < ABMultiValueGetCount(socialRef); i++) {
NSDictionary *socialDictionary = (__bridge NSDictionary *)ABMultiValueCopyValueAtIndex(socialRef, i);
if ([socialDictionary[#"service"] isEqualToString:(__bridge NSString *)kABPersonSocialProfileServiceFacebook]) {
[theContactInfoDictionary setObject:(NSString *)socialDictionary[#"username"] forKey:#"theFacebook"];
} else if ([socialDictionary[#"service"] isEqualToString:(__bridge NSString *)kABPersonSocialProfileServiceTwitter]) {
[theContactInfoDictionary setObject:(NSString *)socialDictionary[#"username"] forKey:#"theTwitter"];
} else if ([socialDictionary[#"service"] isEqualToString:#"Google+"]) {
[theContactInfoDictionary setObject:(NSString *)socialDictionary[#"username"] forKey:#"theGoogle"];
}
}
CFRelease(socialRef);

iOS : Can't get the user email address

I want to get the user mail address, as shown in this thread : Getting user's default email address in Cocoa
But when I tried :
NSString *theEmailAddressWeWantToObtain = #"";
ABPerson *aPerson = [[ABAddressBook sharedAddressBook] me];
ABMultiValue *emails = [aPerson valueForProperty:kABEmailProperty];
if([emails count] > 0)
theEmailAddressWeWantToObtain = [emails valueAtIndex:0];
I have these errors :
Use of undeclared identifier 'aPerson'
Use of undeclared identifier 'ABAddressBook'
Unknown type 'ABMultiValue'
I've linked AddressBook and AddressBookUI, and imported AddressBook/AddressBook.h
What's wrong ?
These are the corrections to your code
NSString *theEmailAddressWeWantToObtain = #"";
ABPerson *aPerson = [[ABAddressBook sharedAddressBook] me];
ABMultiValueRef *emails = [aPerson valueForProperty:kABEmailProperty]; //No such thing as ABMultiValue; it's ABMultiValueRef
if(ABMultiValueGetCount(emails) > 0) //"emails" is not an array, so you can't use the "count" method
theEmailAddressWeWantToObtain = [emails valueAtIndex:0];
I'm not so familiar with Key Value Coding, so I'm not sure about your methods related to that.
This is the way I would do it
There are three email address stored in the email ABMultiValueRef: home, work, and other emails. Try this code to get the home email:
NSString *email;
ABRecordRef currentPerson = (__bridge ABRecordRef)[[PSAddressBook arrayOfContacts] objectAtIndex:identifier];
ABMultiValueRef emailsMultiValueRef = ABRecordCopyValue(currentPerson, kABPersonEmailProperty);
NSUInteger emailsCount;
//Goes through the emails to check which one is the home email
for(emailsCount = 0; emailsCount <= ABMultiValueGetCount(emailsMultiValueRef);emailsCount++){
NSString *emailLabel = (__bridge_transfer NSString *)ABMultiValueCopyLabelAtIndex (emailsMultiValueRef, emailsCount);
if([emailLabel isEqualToString:#"Home"]){
if ((__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(emailsMultiValueRef, emailsCount) != NULL){
email = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonEmailProperty);
}
//If the last name property does not exist
else{
email = #"NULL";
}
}
}
CFRelease(emailsMultiValueRef);
If you have any questions about the code, just ask in the comments. Hope this helps!
EDIT:
The PSAddressBook class mentioned in the code can be found here: https://github.com/pasawaya/PSAddressBook

How to use ABUnknownPersonViewController with generated data entered intially?

This is very specific case. I believe someone had already solved this somewhere, but it's not easy for me to find it.
The situation:
1 ) an object will return NSString objects for name address1, address2, phone:
[anObject name];
[anObject address1];
[anObject address2];
[anObject name];
2 ) I would like to use these objects to prepare ABUnknownPersonViewController with initially entered values, so the user will not have to enter them before saving them in Address Book.
I have looked at iOS documents and searched through Google and StackOverflow, can't find the right answer for this simple situation.
Can anyone guide me on this?
Found an answer: It's nicely documented in iOS Developer Library:
http://developer.apple.com/library/ios/#samplecode/QuickContacts/Listings/Classes_QuickContactsViewController_m.html#//apple_ref/doc/uid/DTS40009475-Classes_QuickContactsViewController_m-DontLinkElementID_6
Here is a sample code I implemented to return a ABPersonRecordRef as an object. The error I had experienced was related to not retaining the ABPersonRecordRef object after returning it.
- (id)personRecordUsingModelObj:(id)modelObj {
ABRecordRef aContact = ABPersonCreate();
CFErrorRef anError = NULL;
NSString *name = [NSString stringWithFormat:#"%#", [modelObj name]];
ABRecordSetValue(aContact, kABPersonOrganizationProperty, name, &anError);
ABMultiValueRef phone = ABMultiValueCreateMutable(kABMultiStringPropertyType);
ABMultiValueAddValueAndLabel(phone, [modelObj phone], kABPersonPhoneMainLabel, NULL);
ABRecordSetValue(aContact, kABPersonPhoneProperty, phone, &anError);
CFRelease(phone);
NSString *address = [NSString stringWithFormat:#"%# %#", [modelObj addr1], [modelObj addr2]];
NSMutableDictionary *dictionaryAddress = [[NSMutableDictionary alloc] initWithCapacity:0];
[dictionaryAddress setObject:address forKey:(NSString *)kABPersonAddressStreetKey];
[dictionaryAddress setObject:#"us" forKey:(NSString *)kABPersonAddressCountryCodeKey];
ABMutableMultiValueRef address = ABMultiValueCreateMutable(kABDictionaryPropertyType);
ABMultiValueAddValueAndLabel(address, dictionaryAddress, kABPersonAddressStreetKey, NULL);
[dictionaryAddress release];
ABRecordSetValue(aContact, kABPersonAddressProperty, address, &anError);
CFRelease(address);
if (anError) {
aContact = nil;
}
[(id)aContact autorelease];
return (id)aContact;
}

Resources