shlist

share and manage lists between multiple people
Log | Files | Refs

AddressBook.m (4221B)


      1 #import "AddressBook.h"
      2 
      3 #include <AddressBook/AddressBook.h>
      4 #import <UIKit/UIKit.h>
      5 
      6 #include "libkern/OSAtomic.h"
      7 
      8 @interface AddressBook ()
      9 
     10 @end
     11 
     12 // empty implementation
     13 @implementation Contact
     14 @end
     15 
     16 @implementation AddressBook
     17 
     18 + (id)shared_address_book
     19 {
     20 	static AddressBook *address_book = nil;
     21 	static dispatch_once_t onceToken;
     22 	dispatch_once(&onceToken, ^{
     23 		address_book = [[self alloc] init];
     24 	});
     25 	return address_book;
     26 }
     27 
     28 - (id)init
     29 {
     30 	self = [super init];
     31 	if (self)
     32 	{
     33 		_contacts = [[NSMutableArray alloc] init];
     34 		ready = 0;
     35 		[self get_contacts_or_fail];
     36 	}
     37 	return self;
     38 }
     39 
     40 - (void) get_contacts_or_fail
     41 {
     42 	ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
     43 
     44 	if (status == kABAuthorizationStatusDenied || status == kABAuthorizationStatusRestricted) {
     45 		// if you got here, user had previously denied/revoked permission for your
     46 		// app to access the contacts, and all you can do is handle this gracefully,
     47 		// perhaps telling the user that they have to go to settings to grant access
     48 		// to contacts
     49 
     50 		[[[UIAlertView alloc] initWithTitle:nil message:@"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
     51 		return;
     52 	}
     53 
     54 	CFErrorRef error = NULL;
     55 	ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
     56 
     57 	if (!addressBook) {
     58 		NSLog(@"ABAddressBookCreateWithOptions error: %@", CFBridgingRelease(error));
     59 		return;
     60 	}
     61 
     62 	// ABAddressBookRegisterExternalChangeCallback(<#ABAddressBookRef addressBook#>, <#ABExternalChangeCallback callback#>, <#void *context#>)
     63 
     64 	ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
     65 		if (error) {
     66 			NSLog(@"ABAddressBookRequestAccessWithCompletion error: %@", CFBridgingRelease(error));
     67 		}
     68 
     69 		if (granted) {
     70 			// if they gave you permission, then just carry on
     71 			[self listPeopleInAddressBook:addressBook];
     72 			if (_main_tvc)
     73 				[_main_tvc update_address_book];
     74 			else
     75 				NSLog(@"warn: address book: address book ready before main_tvc assigned!");
     76 
     77 			// atomically set the ready flag; this completion handler
     78 			// can be run on an arbitrary thread
     79 			OSAtomicIncrement32((volatile int32_t *)&ready);
     80 			[_main_tvc.tableView reloadData];
     81 		} else {
     82 			// however, if they didn't give you permission, handle it gracefully, for example...
     83 
     84 			dispatch_async(dispatch_get_main_queue(), ^{
     85 				// BTW, this is not on the main thread, so dispatch UI updates back to the main queue
     86 
     87 				[[[UIAlertView alloc] initWithTitle:nil message:@"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
     88 			});
     89 		}
     90 
     91 		CFRelease(addressBook);
     92 	});
     93 }
     94 
     95 
     96 - (void)listPeopleInAddressBook:(ABAddressBookRef)addressBook
     97 {
     98 	NSArray *allPeople = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
     99 
    100 	NSCharacterSet *want =[[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet];
    101 
    102 	for (NSInteger i = 0; i < [allPeople count]; i++) {
    103 		ABRecordRef person = (__bridge ABRecordRef)allPeople[i];
    104 		Contact *contact = [[Contact alloc] init];
    105 
    106 		// don't enforce these existing
    107 		contact.first_name = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
    108 		contact.last_name  = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
    109 		contact.phone_numbers = [[NSMutableArray alloc] init];
    110 
    111 		ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
    112 		CFIndex numberOfPhoneNumbers = ABMultiValueGetCount(phoneNumbers);
    113 		for (CFIndex i = 0; i < numberOfPhoneNumbers; i++) {
    114 			NSString *pn = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phoneNumbers, i));
    115 
    116 			if (pn == nil)
    117 				continue;
    118 
    119 			NSString *cleaned = [[pn componentsSeparatedByCharactersInSet: want] componentsJoinedByString:@""];
    120 
    121 			[contact.phone_numbers addObject:cleaned];
    122 		}
    123 		CFRelease(phoneNumbers);
    124 
    125 		[_contacts addObject:contact];
    126 	}
    127 
    128 	_num_contacts = [_contacts count];
    129 	NSLog(@"info: address book: %lu contacts found", _num_contacts);
    130 }
    131 
    132 @end