how to pick the birthday labels from the contacts in Addressbook? - ios

I working with the Addressbook for fetch the contacts list with their labels. (like mobile, main, home, work, fax..etc). I fetched the phone, email labels from the contacts but i did not fetch the birthday, anniversary labels. Here is my code for birthday class.
ABMultiValueRef dateofbirth1 = ABRecordCopyValue(contactPerson, kABPersonBirthdayProperty); // Assign the Date Of birth
NSString *dob1=[NSDateFormatter localizedStringFromDate:(__bridge NSDate *)(dateofbirth1) dateStyle:NSDateFormatterLongStyle timeStyle:0]; // Changing to string format using Date Formatter.
if(!(dob1==nil))
{
// DOB is Not Nill
}
Here is my fetch the BirthDay Label Code
if([arrayOfDatesAsStrings count]>0)
{
for (int j = 0; j < [arrayOfDatesAsStrings count] ; j++)
{
**//This is the fetching birthday label code and following code is crashed**
CFStringRef locLabel1 = ABMultiValueCopyLabelAtIndex((__bridge ABMultiValueRef)(dob1), j);
NSString *phoneLabel1 =(__bridge NSString*) ABAddressBookCopyLocalizedLabel(locLabel1);
personD.dateOfBirth = phone1;
NSLog(#" %# %#",phoneLabel1,personD.dateOfBirth);
}
}
else
{
NSLog(#"Date Of Birth was Not set ");
}
What can i do for this? can Any one help me? The Crash Error Message is :
"Thread 1:Exc_BAD_ACCESS (Code=1, address=0x38)"

To fetch contacts from devices
if (isIOS9) { //checking iOS version of Device
CNContactStore *store = [[CNContactStore alloc] init];
//keys with fetching properties
NSArray *keys = #[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactEmailAddressesKey,CNContactPostalAddressesKey, CNLabelWork, CNLabelDateAnniversary];
NSString *containerId = store.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSError *error;
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
DLOG(#"cnContacts %lu",(unsigned long)cnContacts.count);
if (error) {
//error
} else {
for (CNContact *contact in cnContacts) {
//iterate over cnContacts to get details
}
}
} else {
//for below iOS 9
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef arrPersons = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex count = ABAddressBookGetPersonCount(addressBook);
NSLog(#"cnContacts %lu",(unsigned long)count);
for (int i = 0; i < count; i++) {
ABRecordRef record = CFArrayGetValueAtIndex(arrPersons,i);
//use kABPersonBirthdayProperty to get b’day
NSString *birthDay = (__bridge NSString *)(ABRecordCopyValue(record, kABPersonBirthdayProperty));
NSLog(#“B’day %#”, birthDay);
}
}

Related

How to print the contents of NSSet?

I query and get a NSSet which contains customer address from web. Since I'm new to objective c development I don't know how to get country,zip code etc from that set.So I followed Objective-C How to print NSSet on one line (no trailing comma / space) but my output is in the form of object "0x7f99997b7a50". How can I print all the strings in the set? Thanks in advance.
I tried like this
NSArray *ar = [customer.addresses allObjects];
for (int i = 0; i<ar.count; i++)
{
NSLog(#"arr %#",ar[i]);
}
But the output is arr:
<BUYAddress: 0x7fd451f6e050>
If you have a custom object, you may need to override description
Without overriding:
-(void) testCustomObjects
{
CustomObject *co1 = [[CustomObject alloc] init];
co1.name = #"James Webster";
co1.jobTitle = #"Code Monkey";
CustomObject *co2 = [[CustomObject alloc] init];
co2.name = #"Holly T Canine";
co2.jobTitle = #"Pet Dog";
NSSet *set = [NSSet setWithObjects:co1, co2, nil];
NSLog(#"%#", [set allObjects]);
}
produces:
2016-12-02 11:45:55.342 Playground[95359:4188387] (
"<CustomObject: 0x600000037a20>",
"<CustomObject: 0x60000003ae20>"
)
However, if I override the description method in my CustomObject class:
-(NSString*) description
{
return [NSString stringWithFormat:#"%# (%#)", self.name, self.jobTitle];
}
I get the following:
(
"Holly T Canine (Pet Dog)",
"James Webster (Code Monkey)"
)
If for whatever reason, you can't add a description method, you'd just have to access the relevant parts of the object; something like the following:
NSArray *ar = [customer.addresses allObjects];
for (int i = 0; i<ar.count; i++)
{
NSLog(#"arr %# (%#)",ar[i].name, ar[i].address);
}
I've had a little look at the library you're using. Try the following:
for (BUYAddress *address in customer.addresses)
{
NSLog(#"Address: %#, %#, %#", address.address1, address.address2, address.city);
}
Consider NSSet below,
NSSet *theNSSet = [NSSet setWithObjects:#"Chennai",#"Mumbai",#"Delhi", nil];
Convert it into NSArray using
NSArray *array = [theNSSet allObjects]; // theNSSet is replaced with your NSSet id
Then print it like
NSLog(#"%#",array);
Output im getting
(
Chennai,
Delhi,
Mumbai
)
In your case:
- (NSMutableSet *)addressesSet {
[self willAccessValueForKey:#"addresses"];
NSMutableSet *result = (NSMutableSet *)[self mutableSetValueForKey:#"addresses"];
[self didAccessValueForKey:#"addresses"];
NSLog(#"%#",[result allObjects]); // printing the nsset
return result;
}

Sync iPhone AddressBook with a Backend Server

There are lots of applications doing AddressBook synchronization with their Backend servers to cross check which contacts in your AddressBook are using their application and which users needs to be invited to their application.
For the first time it may do a full sync, but after that it shouldn't be a full sync.
My first question is, What is the best way to sync the full AddressBook with a Backend Server?
Second question is, How to sync ONLY the contacts which has modified recently?
If there's any sample application or a tutorial please share with me.
Thanks in advance.
Hello i am also working on same concept.
First of all i don’t have any tutorial to share with you. But what i am doing in application i am sharing with you entire flow.
When application runs first time i am fetching all the contact numbers and sending to server.
But when any contact modifies i am sending modified contact number only.
You will get a call back from address book when contact is modified. There will be specific record id for each contact
Swift
typealias ABExternalChangeCallback = CFunctionPointer<((ABAddressBook!, CFDictionary!,UnsafeMutablePointer) -> Void)>
From this property you will come to know when your contact was modified recently.
ABRecordCopyValue(record, kABPersonModificationDateProperty).takeRetainedValue() as? NSDate
So either way you can check for contact numbers which were modified recently and then again just send those contact to server.
I hope it may helps you!.
Thanks
Get All Phone number from address book as formatted string and post this string to web-server. this make easy to sent all contact at small delay. at web-server side you can code to split phone number to separate number and check for user with same number.
-(NSString *)getPhoneContactAsSingleString
{
NSString *numberString=[NSString new];
numberString=#"";
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");
#endif
NSMutableArray *contacts=[[NSMutableArray alloc]init];
NSMutableDictionary *numberNameDictionary=[[NSMutableDictionary alloc]init];
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = CFArrayGetCount(allPeople);
for (int i = 0; i < nPeople; i++)
{
NSMutableDictionary *dictionary=[[NSMutableDictionary alloc]init];
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
if (person) {
NSString *firstname=[NSString new];
NSString *lastname =[NSString new];
CFStringRef firstnameStringRef=ABRecordCopyValue(person, kABPersonFirstNameProperty);
CFStringRef lastnameStringRef=ABRecordCopyValue(person, kABPersonLastNameProperty);
if (firstnameStringRef) {
firstname=[NSString stringWithFormat:#"%#",firstnameStringRef];
}
if (lastnameStringRef) {
lastname =[NSString stringWithFormat:#"%#",lastnameStringRef];
}
NSString *name=[NSString new];
if (firstname.length!=0)
{
name=firstname;
if (lastname.length!=0) {
name=[name stringByAppendingString:#" "];
name=[name stringByAppendingString:lastname];
}
}
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
ABMultiValueRef multiPhones = ABRecordCopyValue(person, kABPersonPhoneProperty);
for(CFIndex i=0;i<ABMultiValueGetCount(multiPhones);i++) {
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
NSString *phoneNumber = (__bridge NSString *) phoneNumberRef;
NSString *braketStripedNum = [phoneNumber stringByReplacingOccurrencesOfString:#"(" withString:#""];
braketStripedNum = [braketStripedNum stringByReplacingOccurrencesOfString:#")" withString:#""];
phoneNumber=braketStripedNum;
NSString *dashStripedNum = [self clean_phonenumber:phoneNumber with_string:#"-"];
phoneNumber=dashStripedNum;
NSString *comaStripedNum = [self clean_phonenumber:phoneNumber with_string:#","];
phoneNumber=comaStripedNum;
NSString *dotStripedNum = [self clean_phonenumber:phoneNumber with_string:#"."];
phoneNumber=dotStripedNum;
NSString *spaceStripedNum = [self clean_phonenumber:phoneNumber with_string:#" "];
phoneNumber=spaceStripedNum;
if (phoneNumber.length>10) {
phoneNumber=[phoneNumber substringFromIndex:phoneNumber.length-10];
}
if(phoneNumber.length!=0){
[phoneNumbers addObject:phoneNumber];
[numberNameDictionary setObject:name forKey:phoneNumber];
//NSLog(#"[%#] --> [%#]",orginal_phonenumber,phoneNumber);
numberString=[NSString stringWithFormat:#"%#%#,",numberString,phoneNumber];
}
}
//NSLog(#"%#",phoneNumbers);
if (phoneNumbers.count!=0) {
[dictionary setObject:name forKey:#"name"];
[dictionary setObject:phoneNumbers forKey:#"phonenumbers"];
[contacts addObject:dictionary];
}
}
}
if (numberString.length!=0) {
numberString=[numberString substringToIndex:[numberString length]-1];
}
}
else
{
#ifdef DEBUG
NSLog(#"Cannot fetch Contacts :( ");
#endif
}
return numberString;
}
Clean phone numbers
-(NSString *)clean_phonenumber:(NSString *)number with_string:(NSString *)string
{
NSArray *numberStrips = [number componentsSeparatedByString:string];
NSString *cleanNumber = #"";
for (NSString *eachString in numberStrips) {
cleanNumber = [NSString stringWithFormat:#"%#%#", cleanNumber, eachString];
}
return cleanNumber;
}
Just Check the method
NSLog(#"%#",[self getPhoneContactAsSingleString]);

find ios ABRecordRef contact in AddressBook by phone, email, name

I need to find a contact in AdreesBook in order to add a new social network.
Sometimes I have to find a contact by its phones and emails or by its phones, firstName and lastName, is there any kind of query to get ABRecordRef contact instead of doing whiles?
Many of my users have more than 1000 contacts and I need to update many of them, so it is not efficient if my only solution is to do so many whiles...
Any idea??
Thanks!
Below is method which may help you to get the Contact details using phone number. For that its used kABPersonPhoneProperty, same way you can write another functions for searching email and name:
For email, use a property : kABPersonEmailProperty
For First Name : kABPersonFirstNameProperty
For more details, go through: ABPerson Reference
Hope this helps.
#import <AddressBook/AddressBook.h>
-(NSArray *)contactsContainingPhoneNumber:(NSString *)phoneNumber {
/*
Returns an array of contacts that contain the phone number
*/
// Remove non numeric characters from the phone number
phoneNumber = [[phoneNumber componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] componentsJoinedByString:#""];
// Create a new address book object with data from the Address Book database
CFErrorRef error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (!addressBook) {
return [NSArray array];
} else if (error) {
CFRelease(addressBook);
return [NSArray array];
}
// Requests access to address book data from the user
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {});
// Build a predicate that searches for contacts that contain the phone number
NSPredicate *predicate = [NSPredicate predicateWithBlock: ^(id record, NSDictionary *bindings) {
ABMultiValueRef phoneNumbers = ABRecordCopyValue( (__bridge ABRecordRef)record, kABPersonPhoneProperty);
BOOL result = NO;
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
NSString *contactPhoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
contactPhoneNumber = [[contactPhoneNumber componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] componentsJoinedByString:#""];
if ([contactPhoneNumber rangeOfString:phoneNumber].location != NSNotFound) {
result = YES;
break;
}
}
CFRelease(phoneNumbers);
return result;
}];
// Search the users contacts for contacts that contain the phone number
NSArray *allPeople = (NSArray *)CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
NSArray *filteredContacts = [allPeople filteredArrayUsingPredicate:predicate];
CFRelease(addressBook);
return filteredContacts;
}

Getting most recent BMI value from HKHealthStore

I want to get the users most recent BMI reading from my instance of HKHealthStore. As of right now I am doing it as follows but it doesn't seem right. Is there a way to get an actual numerical value for BMI instead of a countUnit (HKUnit)?
HKQuantityType *bodyMassIndexType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMassIndex];
HKSampleQuery *bmiSampleQuery = [[HKSampleQuery alloc] initWithSampleType:bodyMassIndexType predicate:nil limit:1 sortDescriptors:nil resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error) {
if (results.count == 0)
{
//No results
}
else
{
if (!error)
{
NSString *bmiString = [NSString stringWithFormat:#"%#", [[results firstObject] quantity]];
NSString *parsedBMIString = [bmiString stringByReplacingOccurrencesOfString:#" count" withString:#""];
NSLog(#"%f", [parsedBMIString floatValue]);
}
}
}];
[self.store executeQuery:bmiSampleQuery];
The sample returns an array, so you can simply pull out the first object from the array and then convert it's value to a double for handling.
HKQuantitySample *sample = [results firstObject];
int i = [sample.quantity doubleValueForUnit:[HKUnit countUnit]];
NSLog(#"%i",i);

Pull out valueForKeys of an inner NSMutableDictionary iOS

Ok I get and store a Json feed to an array called jsonArray. I then loop over the jsonArray pulling out the array keys and storing them as strings. I then add those strings to an inner dictionary called innerDict, I then add that dictionary to the info dictionary with the key thePostCode using the below. So basically innerDict is stored inside infoDict.
-(void)pointInfo{
infoDict = [[NSMutableDictionary alloc]init];
for (int i = 0; i < jsonArray.count; i++) {
innerDict = [[NSMutableDictionary alloc]init];
info = [[jsonArray objectAtIndex:i]objectForKey:#"inf"];
thePostCode = [[jsonArray objectAtIndex:i]objectForKey:#"pc"];
mail = [[jsonArray objectAtIndex:i]objectForKey:#"mail"];
url = [[jsonArray objectAtIndex:i]objectForKey:#"url"];
type = [[jsonArray objectAtIndex:i]objectForKey:#"items"];
[innerDict setObject:type forKey:#"Items"];
[innerDict setObject:info forKey:#"Info"];
[innerDict setObject:mail forKey:#"Mail"];
[innerDict setObject:url forKey:#"Url"];
[infoDict setObject:innerDict forKey:thePostCode];
}
the output of infoDict looks like this:
infoDict is {
"ME14 4NN" = {
Info = "";
Items = 4;
Mail = "";
Url = "";
};
"ME15 6LG" = {
Info = af;
Items = "0,6,9";
Mail = "";
Url = "";
};
"ME15 6YE" = {
Info = "";
Items = "4,5,6,7,11";
Mail = "";
Url = "";
};
}
Now what I want to do is get the values of the innerDict object i.e "ME15 6YE" above and use that as the query to pull out the associated data for Info, Items, Mail and Url keys. I have been staring at my screen for a few hours but I am just not getting it.
I can pull out the last object of the inner dict using the below however I would like to grab all the values associated with a particular postcode which would be the innerDict key. Completely brain fried at the moment!
for (NSMutableDictionary *dictionary in infoDict) {
NSLog(#"URL %#", [innerDict objectForKey:#"Url"]);
NSLog(#"MAIL %#", [innerDict objectForKey:#"Mail"]);
NSLog(#"ITEMS %#", [innerDict objectForKey:#"Items"]);
NSLog(#"ITEMS %#", [innerDict objectForKey:#"Info"]);
}
To get the correct inner dictionary, use objectForKey:
NSDictionary *innerDict = [infoDict objectForKey:#"ME15 6YE"];
NSLog(#"Url %#", [innerDict objectForKey:#"Url"]);
NSLog(#"Mail %#", [innerDict objectForKey:#"Mail"]);
NSLog(#"Items %#", [innerDict objectForKey:#"Items"]);
NSLog(#"Info %#", [innerDict objectForKey:#"Info"]);
Maybe I'm misunderstanding something, but I think this should answer your questions.
You're using dictionary in the for loop, but trying to access it via innerDict. Change it to:
for (NSMutableDictionary *dictionary in infoDict) {
NSLog(#"URL %#", [dictionary objectForKey:#"Url"]);
NSLog(#"MAIL %#", [dictionary objectForKey:#"Mail"]);
NSLog(#"ITEMS %#", [dictionary objectForKey:#"Items"]);
NSLog(#"ITEMS %#", [dictionary objectForKey:#"Info"]);
}
Or, for a single one,
NSMutableDictionary *inner = [infoDict objectForKey:#"POST CODE HERE"];
NSLog(#"URL %#", [inner objectForKey:#"Url"]);
NSLog(#"MAIL %#", [inner objectForKey:#"Mail"]);
NSLog(#"ITEMS %#", [inner objectForKey:#"Items"]);
NSLog(#"ITEMS %#", [inner objectForKey:#"Info"]);

Resources