6

I am attempting to create an app that can be used to search an Exchange GAL, however, I am finding the new 4.0 documentation regarding this subject confusing. Does anyone know how I might go about searching the GAL for names containing a specific string (e.g. "Smi")? My source code at the moment is all but useless as I am simply trying to wrap my head around how to specify that I am wanting only to search the GAL and not the local contacts on the device. Also, how is kABSourceTypeSearchableMask used? I am missing something fundamental here. From the documentation...

Source Types

These constants identify the type of a source.

enum {
    kABSourceTypeLocal       = 0x0,
    kABSourceTypeExchange    = 0x1,
    kABSourceTypeExchangeGAL = kABSourceTypeExchange | kABSourceTypeSearchableMask,
    kABSourceTypeMobileMe    = 0x2,
    kABSourceTypeLDAP        = 0x3 | kABSourceTypeSearchableMask,
    kABSourceTypeCardDAV     = 0x4,
    kABSourceTypeCardDAVSearch = kABSourceTypeCardDAV | kABSourceTypeSearchableMask,
};
typedef int ABSourceType;

When I query for the default source type, I do get "1" which would appear to indicate that the default type is "kABSourceTypeExchange" which would be correct as this is what I have in my Settings. I do not know how to proceed beyond this point...

As the whole source concept is a new to the ABAddressBook framework in 4.0 I don't imagine that folks have much experience with this, but hoping someone might help me understand how to work with the above...thanks.

rob5408
  • 2,886
  • 2
  • 37
  • 50
JfgDev
  • 61
  • 1
  • 4
  • Hey, did you ever find a solution to enable you to search the GAL? I'm going round in circles with this one, there doesn't seem to be any answer. See my new question here: http://stackoverflow.com/questions/17566267/ios-how-to-search-a-searchable-absource-with-absourcetype-kabsourcetypese – Sam Jul 11 '13 at 17:15

3 Answers3

7

To get access to the Exchange GAL, you'll need to use the function ABAddressBookCopyArrayOfAllSources to get an array of all sources, and then iterate over the array to try and get the correct source for the Exchange GAL. Use the ABRecordCopyValue() function to get the kABSourceTypeProperty property of the source.

e.g.

ABRecordRef searchableExchangeSource;

addressBook = ABAddressBookCreate();
CFArrayRef allSources = ABAddressBookCopyArrayOfAllSources(addressBook);
for (CFIndex i = 0; i < CFArrayGetCount(allSources); i++) {
    ABRecordRef source = (ABRecordRef)CFArrayGetValueAtIndex(allSources, i);

    // Get source properties
    NSNumber *sourceTypeRef = (NSNumber *)((CFNumberRef)ABRecordCopyValue(source, kABSourceTypeProperty));
    NSString *sourceTypeName = (NSString *)((CFStringRef)ABRecordCopyValue(source, kABSourceNameProperty));
    int sourceType = [sourceTypeRef intValue];
    NSLog(@"Found Source Type: %@ with ABSourceType %i", sourceTypeName,sourceType);
    if (sourceType == kABSourceTypeExchangeGAL) {
        searchableExchangeSource = source;
    }
    [sourceTypeRef release];
    [sourceTypeName release];
}

Note if you have multiple "Exchange" accounts set up you will get multiple sources with the same ABSourceType. Unfortunately from my limited testing, the kABSourceTypeNameProperty for Exchange GALs is NULL so you can't use this property to differentiate between multiple Exchange GAL sources.

Once you have the appropriate source, it is of the type ABRecordRef so you can interact with it just like any other record.

mixja
  • 5,619
  • 3
  • 26
  • 31
  • This enables you to find the source, but then what can you do with the source? Is there any way to search for contacts within the source, e.g. "Smi" in the OP, to return "John Smith", etc. – Sam Jul 09 '13 at 17:14
1

I posted some code here: Obtaining Specific ABSource from ABAddressBook in iOS 4+

for identifying specific sources. It may be useful in helping you to see how to work with ABAddressBook.

Community
  • 1
  • 1
xyzzycoder
  • 1,821
  • 13
  • 19
0

Update for Mixja's response

  1. ABAddressBookCreate() has been deprecated. Declare a reference in interface:
    • Also, remove: addressBook = ABAddressBookCreate();
  2. Update the declaration of sourceTypeRef & sourceTypeName:
  3. Change the release method calls to:

    // 1.
    @property(nonatomic, assign) ABAddressBookRef *addressBook;
    // 2.
    NSNumber *sourceTypeRef = (__bridge NSNumber *)((CFNumberRef)ABRecordCopyValue(source, kABSourceTypeProperty));
    NSString *sourceTypeName = (__bridge NSString *)((CFStringRef)ABRecordCopyValue(source, kABSourceNameProperty));
    
    // 3.
    CFRelease((__bridge CFTypeRef)(sourceTypeRef));
    CFRelease((__bridge CFTypeRef)(sourceTypeName));
    

Final code should look something like this:

Make sure to include step 1!

    ABRecordRef searchableExchangeSource;

    CFArrayRef allSources = ABAddressBookCopyArrayOfAllSources(_addressBook);
    for (CFIndex i = 0; i < CFArrayGetCount(allSources); i++) {
    ABRecordRef source = (ABRecordRef)CFArrayGetValueAtIndex(allSources, i);

    // Get source properties
    NSNumber *sourceTypeRef = (__bridge NSNumber *)((CFNumberRef)ABRecordCopyValue(source, kABSourceTypeProperty));
    NSString *sourceTypeName = (__bridge NSString *)((CFStringRef)ABRecordCopyValue(source, kABSourceNameProperty));
    int sourceType = [sourceTypeRef intValue];
    NSLog(@"Found Source Type: %@ with ABSourceType %i", sourceTypeName,sourceType);
    if (sourceType == kABSourceTypeExchangeGAL) {
        searchableExchangeSource = source;
    }
    CFRelease((__bridge CFTypeRef)(sourceTypeRef));
    CFRelease((__bridge CFTypeRef)(sourceTypeName));
ChrisHaze
  • 2,760
  • 14
  • 19