Adding vCard data directly to the system Address Book
Asked Answered
I

3

10

I am designing a QR code reader, and it needs to detect and import contact cards in vCard format (.vcf).

is there a way to add the card data to the system Address Book directly, or do I need to parse the vCard myself and add each field individually?

Instructive answered 14/11, 2011 at 1:4 Comment(6)
There is a function, ABPersonCreatePeopleInSourceWithVCardRepresentation() to important VCF data, but it was only added in iOS 5. What version of iOS are you targeting?Objective
Well I am not sure yet about the version probably the latest one. My app will be for iPhone 4 and 4s for now and I am using an iPhone 4s to test it to ios5(and later) should be good thanksInstructive
In what variable type do you have the VCF data? NSData, NSString, or just a path to an actual file?Objective
It will probably be Nsstring. any advice ?Instructive
Check my answer! I hope that works.Objective
It's not Vcard in QR codes, but meCard en.wikipedia.org/wiki/MeCard.Burial
O
13

If you're running on iOS 5 or later, this code should do the trick:

#import <AddressBook/AddressBook.h>

// This gets the vCard data from a file in the app bundle called vCard.vcf
//NSURL *vCardURL = [[NSBundle bundleForClass:self.class] URLForResource:@"vCard" withExtension:@"vcf"];
//CFDataRef vCardData = (CFDataRef)[NSData dataWithContentsOfURL:vCardURL];

// This version simply uses a string. I'm assuming you'll get that from somewhere else.
NSString *vCardString = @"vCardDataHere";
// This line converts the string to a CFData object using a simple cast, which doesn't work under ARC
CFDataRef vCardData = (CFDataRef)[vCardString dataUsingEncoding:NSUTF8StringEncoding];
// If you're using ARC, use this line instead:
//CFDataRef vCardData = (__bridge CFDataRef)[vCardString dataUsingEncoding:NSUTF8StringEncoding];

ABAddressBookRef book = ABAddressBookCreate();
ABRecordRef defaultSource = ABAddressBookCopyDefaultSource(book);
CFArrayRef vCardPeople = ABPersonCreatePeopleInSourceWithVCardRepresentation(defaultSource, vCardData);
for (CFIndex index = 0; index < CFArrayGetCount(vCardPeople); index++) {
    ABRecordRef person = CFArrayGetValueAtIndex(vCardPeople, index);
    ABAddressBookAddRecord(book, person, NULL);
}

CFRelease(vCardPeople);
CFRelease(defaultSource);
ABAddressBookSave(book, NULL);
CFRelease(book);

Make sure to link to the AddressBook framework in your project.

Objective answered 14/11, 2011 at 2:54 Comment(10)
I am in a situation where I will be deciding what the QR code data type will be reading , all I know is that the format of the text will be like this :Instructive
BEGIN:VCARD N;CHARSET=utf-8:<last name>;<first name>;;; FN;CHARSET=utf-8:<full name> ORG;CHARSET=utf-8:<company name> TITLE;CHARSET=utf-8:<title> TEL;WORK:<telephone number> TEL;WORK;FAX:<fax number> EMAIL;INTERNET;WORK;CHARSET=utf-8:<email> ADR;WORK;CHARSET=utf-8:;;<address including zip code , state and country> URL;WORK;CHARSET=utf-8:<website> VERSION:2.1 END:VCARD now considering that it will be spread on several lines , can I say that it is an NSString or will the NSSstring will only take the first line of this text ? (I am fairly new to objective C )Instructive
NSString can easily store multiple lines of text.Objective
I used this code but it is not working First it does not compile this line : CFDataRef vCardData = (CFDataRef)[vCardString dataUsingEncoding:NSUTF8StringEncoding]; I have to change it to this : CFDataRef vCardData = (__bridge CFDataRef)[vCardString dataUsingEncoding:NSUTF8StringEncoding]; then when it runs it does crashes at this line : for (CFIndex index = 0; index < CFArrayGetCount(vCardPeople); index++) {Instructive
I used this code but it is not working First it does not compile this line : CFDataRef vCardData = (CFDataRef)[vCardString dataUsingEncoding:NSUTF8StringEncoding]; I have to change it to this : CFDataRef vCardData = (__bridge CFDataRef)[vCardString dataUsingEncoding:NSUTF8StringEncoding]; then when it runs it does crashes at this line : for (CFIndex index = 0; index < CFArrayGetCount(vCardPeople); index++) { it gives the following green error : Tread1:Program Received Signal "EXC_BAD_ACCESS" any reasons ?Instructive
The bridge code was required because you're using ARC, so that makes sense. Here's the simplest possible problem: are you feeding it a valid vCard string? Or are you just using my placeholder? If you're using the placeholder, that definitely won't work. You need to have a valid vCard string.Objective
Hello I do have a VCard String , I changed "__bridge" to "__bridge_retained" and still no luck , it compiles and runs but it does not save in the address bookInstructive
I'd like to help more, but it's getting annoying to have to flag all the duplicate questions you're asking. Please stick to this one question, and we can try and figure this out.Objective
CFRelease(person); is not required and will crash. Ref: developer.apple.com/library/mac/#documentation/CoreFOundation/…Stahl
how about before iOS 5?Macaronic
B
4

Carter Allen's answer worked for me except that it caused my app to crash on the final statement CFRelease(book);

It turns out that the CFRelease(person); statement should be removed. Doing so stopped my app from crashing. See this answer for explanation https://mcmap.net/q/1162855/-iphone-sdk-exc_bad_access-with-cfrelease-for-abaddressbookref

Also checkout The Create Rule and The Get Rule sections on this page https://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html

Bleach answered 29/2, 2012 at 22:19 Comment(0)
O
1

Contacts is pretty forgiving and will do its best to import your vCard, however it seems that your address is not correct. There should be 7 parameters, separated by semicolons: PO box, Suite #, street address, city, state, ZIP, country. Most people leave off the PO box (and suite #), which is why a typical address has a semicolon (or two) at the beginning. If your address is ill-formed, parameters might end up in the wrong places.

The various fields in a vCard are terminated by a <return>: @"\r"

You don't need CHARSET=utf-8

Orientalism answered 24/9, 2012 at 2:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.