iphone sdk addressbook - get ABRecordRef - iphone

in the method
- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
im trying to simply access ABRecordRef as a variable, but i keep getting the error
expected expression before 'ABRecordRef'.
I can already get names and company info, but not the ABRecordRef.
What I am doing is:
NSLog(#"Contact Reference: %d", ABRecordRef);

Did you
#import <AddressBook/AddressBook.h>
? And what do you mean by
contactRef = [NSString stringWithFormat:#"%d", ABRecordRef];
? It doesn't make sense considering ABRecordRef is a type, not a number.

Related

How to access the Device token from didRegisterForRemoteNotificationsWithDeviceToken to my ViewDidLoad method

I know this is very basic but I need to pull my device token and Store it in a String and put(display) it on a label on my ViewDidLoad method. What might be the posible solution? Im new on iOS development. Should I use Global variable? or any Posible Solution?
This is my code.
AppDelegate.m
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString *str = [NSString stringWithFormat:#"Device Token=%#",deviceToken];
NSLog(#"%#", str);
//get the string and display it on the ViewDidLoad method.
}
Please help me. How to use global variable to access that string?
on my ViewController.m class
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *getToken = #"Token from AppDelegate";
}
Something like that.
You can store the token into user defaults:
[[NSUserDefaults standardUserDefaults] setValue:str forKey:#"DEVICE_TOKEN"];
And then in your viewDidLoad:
NSString *getToken = [[NSUserDefaults standardUserDefaults] stringForKey:#"DEVICE_TOKEN"];
But there are other approaches: global variable, persistence layer, NSNotification, and so on.
EDIT:
Here you have info about how to register the standard user defaults.
EDIT2:
In order to obtain the token string, I do the following
NSString *deviceTokenString = [deviceToken description];
deviceTokenString = [deviceTokenString stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"<>"]];
deviceTokenString = [deviceTokenString stringByReplacingOccurrencesOfString:#" " withString:#""];
Then, in deviceTokenString you end having the full value without whitespaces or any other character. Just ready to trigger push notifications.
I usually create a category on UIApplication (or a UIApplication subclass) for storing the current push token.
#interface MyApplication : UIApplication
#property (nonatomic, copy) NSData *pushToken;
#end
As #amb mentioned, there are a lot of different ways to go about it.

Retrieve selected group from native contact application

I am working on one application in which I need to show contacts from the contact application.
I have successfully implemented the functionality but now I need to only show the contacts from the groups which are selected in native contact application similar Magic Jack(http://itunes.apple.com/us/app/free-calls-with-magicjack/id463926997?mt=8) iPhone app.
I have tried to search on google, forums, apple's documentation but didn't able to find the solution. Can anyone help me?
I am using below code to fetch all contact information.
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
NSArray *persons = (NSArray *)(ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName));
Here is code you can use,it fetch the first and last name.
-(IBAction)handlingClick:(id)sender
{
ABPeoplePickerNavigationController *peopleController = [[ABPeoplePickerNavigationController alloc] init];
peopleController.peoplePickerDelegate = self;
[self presentModalViewController:peopleController animated:YES];
[peopleController release];
}
-(void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
[peoplePicker dismissModalViewControllerAnimated:YES];
}
-(BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier
{
return NO;
}
-(BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
self.firstName.text = (NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
self.lastName.text = (NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);
[self dismissModalViewControllerAnimated:YES];
return NO;
}
Is ABGroupCopyArrayOfAllMembers not suitable for what you want?

contact notes are not transferred when exporting/importing via the built-in vCard representation methods

Using the ABPersonCreateVCardRepresentationWithPeople method for export, and the ABPersonCreatePeopleInSourceWithVCardRepresentation for import, I have successfully transfered contact data between devices. However, the data in the contact's "notes" field isn't transfered.
Here's my export function:
+(NSData*)exportContactsToVcard:(NSArray*)contacts
{
NSMutableArray *people = [NSMutableArray arrayWithCapacity:contacts.count];
ABAddressBookRef ab = ABAddressBookCreate();
for (Contact *contact in contacts)
{
ABRecordRef person = ABAddressBookGetPersonWithRecordID(ab,contact.contactId);
[people addObject:(__bridge id)person];
}
NSData *vCard = (__bridge NSData*)ABPersonCreateVCardRepresentationWithPeople((__bridge CFArrayRef) people);
return vCard;
}
and part of my import function:
+(NSArray*)importContactsFromVcardData:(NSData*)vcardData
{
NSMutableArray *addedContactIds = [NSMutableArray array];
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef defaultSource = ABAddressBookCopyDefaultSource(addressBook);
NSArray *createdPeople = (__bridge_transfer NSArray*)ABPersonCreatePeopleInSourceWithVCardRepresentation(defaultSource,(__bridge CFDataRef)vcardData);
CFErrorRef error = NULL;
for (id person in createdPeople)
{
error = NULL;
ABRecordRef personRecord = (__bridge ABRecordRef)person;
NSString *notes = (__bridge NSString *)ABRecordCopyValue(personRecord, kABPersonNoteProperty);
In the last line, notes is always nil, even if the contact had notes before it was exported. All the other standard contact fields seem to be in place.
For example, if I replace the last line with:
NSString *firstName = (__bridge NSString *)ABRecordCopyValue(personRecord, kABPersonFirstNameProperty);
the firstName string will hold the contact's first name.
Any idea how I can work around this, and get the contact notes?
Thanks.
For testing purposes, you can export a vCard from Address Book. Then drag it to TextEdit to look at the various fields.
At the bottom you'll find something like this:
NOTE:This is a note!
Also, see this link for info on the vCard format:
http://en.wikipedia.org/wiki/VCard
ABPersonCreateVCardRepresentationWithPeople will only transfer the important contact details of a vCard...thats my identifying in much tests with the vCard and the iOS import-export function. It has many mistakes, e.g. if you try to import it with social networks like facebook, it won't do it with (just look in my other thread THREADLINK )
But if you try to add some vCard Information over ABNewPersonViewController, it will work perfectly.

Setting person properties

Working on someone else's code. I am really confused about whats exactly happening in this code.
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef persons = ABAddressBookGetPersonWithRecordID(addressBook, x);
CFErrorRef *error=NULL;
ABAddressBookRemoveRecord(addressBook, persons, error);
ABAddressBookSave(addressBook, error);
ABRecordRef persons = ABPersonCreate();
ABRecordSetValue(persons, kABPersonFirstNameProperty, firstName , nil);
What should be done is that, a ABRecordRef person should be created. His properties should be set and his record/details should be displayed. He should never be saved in the address book. Is this the way to do it. Need help.
Edit: Apart from setting properties to person, the following code is added to push the view controller to view the person.
MyContactDetailViewcontroller *personContactDetail = [[MyContactDetailViewcontroller alloc] init];
personContactDetail.displayedPerson = persons;
personContactDetail.passedSelectedContactData = selectedContactsOnlyData;
[self.navigationController pushViewController:personContactDetail animated:YES];
[personContactDetail release];
MyContactDetailViewcontroller subclass ABPersonViewController. Or is it more apt to use ABUnknownPersonViewController.
Do you find any cases where the contacts could be duplicated in address book
This is exactly what is happening here.. I will explain..
ABAddressBookCreate creates a new address book from data from the addressbook database, so any changes you make to ABAddressBookRef will only be saved to actual addressbook database once you call ABAddressBookSave(). so what it is doing is getting the reference for the person with recordid- x. Than you are creating a new person entry using
ABRecordRef persons = ABPersonCreate();
and than you are setting its value, but this is available to this particular object and not stored in the database unless you call... ABAddressBookSave()
hoping this helps you... :)

Memory leak with CFArray in ARC

I've made an iPhone app using ARC that accesses every entry in the address book, and then every address for every person. The data is stored in CFArrays, which are toll-free bridged to NSArrays. The code is below.
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef arrayRef = ABAddressBookCopyArrayOfAllPeople(addressBook);
NSArray *peopleArray =[(__bridge NSArray *) arrayRef copy];
CFRelease(arrayRef);
arrayRef = nil;
for(id personId in peopleArray)
{
ABRecordRef person = (__bridge ABRecordRef) personId;
//process other attributes of the address book
ABMultiValueRef multi = ABRecordCopyValue(person, kABPersonAddressProperty);
CFArrayRef addressRef = ABMultiValueCopyArrayOfAllValues(multi);
NSArray *addressArray = [(__bridge NSArray *) addressRef copy];
for(NSDictionary *address in addressArray)
{
//process the addresses
}
CFRelease(addressRef);
addressRef = nil;
}
From what I've researched on the internet and in Apple's Memory Management guides, this looks like the proper way to do it. The problem is when I got to run the code, it halts on "CFRelease(addressRef)", highlighted green with text "Thread 1" (not sure what this error means). I've also tried putting the CFRelease before the for loop, but the same issue occurs.
If I remove the CFRelease, it compiles, but there is a memory leak at the creation of addressArray. Does anyone know how to solve this problem? I can't seem to figure it out using ARC.
Instead of NSArray *peopleArray =[(__bridge NSArray *) arrayRef copy]; CFRelease(arrayRef);, use NSArray *peopleArray = CFBridgingRelease(arrayRef). This transfers ownership of the object to ARC.
Whenever you see "Copy" in a method name you should use (__bridge_transfer <ObjectType> *)
Then ARC will be responsible for releasing the object.
So your code will look like:
NSArray *peopleArray = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);