3

Does anyone have an example of how to obtain a specific ABSource from the ABAddressBook in iOS 4+?

xyzzycoder
  • 1,821
  • 13
  • 19

4 Answers4

9

iOS 4+ provides new API that allows one to select a specific ABSource from the ABAddressBook. This may be useful as some operations, e.g. creating an ABGroup, are not supported in some sources (i.e. Exchange).

"Not all source types support groups, more conspicuously, Exchange does not know anything about groups." - http://flavors.me/volonbolon#1a5/tumblr

Attached are functions that leverage the new API to obtain sources of specific types which may be used in calls to ABGroupCreateInSource().

#define CFRELEASE_AND_NIL(x) CFRelease(x); x=nil;
ABRecordRef sourceWithType (ABSourceType mySourceType)
{
    ABAddressBookRef addressBook = ABAddressBookCreate();
    CFArrayRef sources = ABAddressBookCopyArrayOfAllSources(addressBook);
    CFIndex sourceCount = CFArrayGetCount(sources);
    ABRecordRef resultSource = NULL;
    for (CFIndex i = 0 ; i < sourceCount; i++) {
        ABRecordRef currentSource = CFArrayGetValueAtIndex(sources, i);
        CFTypeRef sourceType = ABRecordCopyValue(currentSource, kABSourceTypeProperty);

        BOOL isMatch = mySourceType == [(NSNumber *)sourceType intValue];
        CFRELEASE_AND_NIL(sourceType);

        if (isMatch) {
            resultSource = currentSource;
            break;
        }
    }

    CFRELEASE_AND_NIL(addressBook);    
    CFRELEASE_AND_NIL(sources);

    return resultSource;
}

ABRecordRef localSource()
{
    return sourceWithType(kABSourceTypeLocal);
}

ABRecordRef exchangeSource()
{
    return sourceWithType(kABSourceTypeExchange);
}

ABRecordRef mobileMeSource()
{
    return sourceWithType(kABSourceTypeMobileMe);
}
xyzzycoder
  • 1,821
  • 13
  • 19
  • 4
    Readers, be aware that not all devices will have a local source (see comments below), so you will need to be able to handle cases where the requested source does not exist. It also does not appear to be possible to programmatically create a local source. – xyzzycoder Feb 17 '11 at 09:45
  • what about releasing the copied values? Is this unnecessary for some reason I don't see? – Martin Reichl Mar 14 '11 at 10:31
  • Martin - Good catch. The leaks should be fixed now. – xyzzycoder Mar 30 '11 at 02:14
2

Really wanna know how to create my own source.Just like the group Exchange create with which you dont need to edit the default source record but create own one,and what's most fantastic is,the addressbook will linked them together automatically.

  • Jackie, are you saying that you know how to create a local source? – xyzzycoder Jan 29 '11 at 06:34
  • 1
    I wish.Actually I found a private API that can create my own source which is ABSourceCreate();.It doesnt crash and return ABRecordRef which is printed as "ABStore" type in Log.I believe that is the ABSource type that i want.So I set the kABSourceNameProperty,kABSourceTypeProperty and use ABAddressAddRecord() to add it to addressBook.But it is still failed finally like i had missed something in process.Maybe Apple will release some more detail in next update,who knows : ) – Jackie Cheung Jan 30 '11 at 07:25
1

Xyzzycoder-

Your solution works well if there is already a localSource, but just returns NULL if there isn't one.

Is there a way to, say, create an ABRecordRef for a localSource? I need to be able to store my contact to a non-synchronising source.

Cheers

Peter Johnson
  • 3,663
  • 1
  • 20
  • 26
  • Peter, under what circumstances would there not be a local source? – xyzzycoder Jan 20 '11 at 00:01
  • Hi. For example there is no local address book (typically "all on my iphone", "all on my PC" or "all on my Mac" listed on the Groups page on the Contacts app) if you synchronize all your contacts with Google over Exchange, neither can you get a handle to it using the method you suggested. From my testing you can only get a handle on a local addressbook if the user also has some contacts stored on his device that dont sync to Exchange (if he entered them before he had Exchange set up, for instance, and opted not to merge). Cheers – Peter Johnson Jan 24 '11 at 12:57
  • Peter, that's interesting. I guess that I had (apparently wrongly) assumed that a local address book would always exist on the device. It also does not seem like there is a facility for programmatically creating the local source if it does not already exist? – xyzzycoder Jan 25 '11 at 08:57
1

The code has errors, thats why it always returns two, since the method: ABRecordGetRecordType is not a part of the ABSource. It only includes:

kABPersonType for person records kABGroupType for group records. kABSourceType for source records.

To figure out the right type you have to use: ABRecordCopyValue(source, kABSourceTypeProperty) instead! :) Works excellent on my iPhone with or without localSource.

Good luck!

hinderberg
  • 404
  • 1
  • 3
  • 11
  • @hinderberg - can you patch the code to incorporate what you're suggesting? Or are you saying that the approach just will not work if the local source does not already exist? – xyzzycoder Feb 11 '11 at 06:53
  • I'm saying that this approach will not work if the local source does not already exist. Currently waiting on a answer from Apple on this issue! – hinderberg Feb 14 '11 at 21:52
  • @xyzzycoder got an answer from Apple today and it was as I thought. "It is not possible to create a source, or perform any operations on a source the user is not using." I have filed a bug on -> http://developer.apple.com/bugreporter/ – hinderberg Feb 15 '11 at 08:18
  • @hinderberg - Thank you. I would still like to patch the code example so that it works, to the degree that it can. – xyzzycoder Feb 15 '11 at 09:54
  • @hinderberg - I believe that I have incorporated the patch that you suggested. Thank you. – xyzzycoder Feb 17 '11 at 09:21