Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

First Commit

  • Loading branch information...
commit 2dfc5d265389764c9ebf034771c6b48be7603811 0 parents
Erica Sadun authored
94 ABContact.h
@@ -0,0 +1,94 @@
+/*
+ Erica Sadun, http://ericasadun.com
+ iPhone Developer's Cookbook, 3.0 Edition
+ BSD License, Use at your own risk
+ */
+
+#import <UIKit/UIKit.h>
+#import <AddressBook/AddressBook.h>
+#import <AddressBookUI/AddressBookUI.h>
+
+@interface ABContact : NSObject
+{
+ ABRecordRef record;
+}
+
+// Convenience methods
++ (id) contact;
++ (id) contactWithRecord: (ABRecordRef) record;
+
+// Class utility methods
++ (NSString *) cleanLabel: (NSString *) aLabel;
++ (CFStringRef) formattedLabel: (NSString *) aLabel;
++ (NSString *) localizedPropertyName: (ABPropertyID) aProperty;
++ (ABPropertyType) propertyType: (ABPropertyID) aProperty;
++ (NSString *) propertyTypeString: (ABPropertyID) aProperty;
+
+// Creating proper dictionaries
++ (NSDictionary *) dictionaryWithValue: (id) value andLabel: (CFStringRef) label;
++ (NSDictionary *) addressWithStreet: (NSString *) street withCity: (NSString *) city
+ withState:(NSString *) state withZip: (NSString *) zip
+ withCountry: (NSString *) country withCode: (NSString *) code;
++ (NSDictionary *) smsWithService: (CFStringRef) service andUser: (NSString *) userName;
+
+// Instance utility methods
+- (NSString *) removeSelfFromAddressBook;
+
+@property (readonly) ABRecordRef record;
+@property (readonly) ABRecordID recordID;
+@property (readonly) ABRecordType recordType;
+@property (readonly) BOOL isPerson;
+
+#pragma mark SINGLE VALUE STRING
+@property (assign) NSString *firstname;
+@property (assign) NSString *lastname;
+@property (assign) NSString *middlename;
+@property (assign) NSString *prefix;
+@property (assign) NSString *suffix;
+@property (assign) NSString *nickname;
+@property (assign) NSString *firstnamephonetic;
+@property (assign) NSString *lastnamephonetic;
+@property (assign) NSString *middlenamephonetic;
+@property (assign) NSString *organization;
+@property (assign) NSString *jobtitle;
+@property (assign) NSString *department;
+@property (assign) NSString *note;
+
+@property (readonly) NSString *contactName; // my friendly utility
+@property (readonly) NSString *compositeName; // via AB
+
+#pragma mark DATE
+@property (readonly) NSDate *birthday;
+@property (readonly) NSDate *creationDate;
+@property (readonly) NSDate *modificationDate;
+
+#pragma mark MULTIVALUE
+// Each of these produces an array of NSStrings
+@property (readonly) NSArray *emailArray;
+@property (readonly) NSArray *emailLabels;
+@property (readonly) NSArray *phoneArray;
+@property (readonly) NSArray *phoneLabels;
+@property (readonly) NSArray *relatedNameArray;
+@property (readonly) NSArray *relatedNameLabels;
+@property (readonly) NSArray *urlArray;
+@property (readonly) NSArray *urlLabels;
+@property (readonly) NSArray *dateArray;
+@property (readonly) NSArray *dateLabels;
+@property (readonly) NSArray *addressArray;
+@property (readonly) NSArray *addressLabels;
+@property (readonly) NSArray *smsArray;
+@property (readonly) NSArray *smsLabels;
+
+// Each of these uses an array of dictionaries
+@property (assign) NSArray *emailDictionaries;
+@property (assign) NSArray *phoneDictionaries;
+@property (assign) NSArray *relatedNameDictionaries;
+@property (assign) NSArray *urlDictionaries;
+@property (assign) NSArray *dateDictionaries;
+@property (assign) NSArray *addressDictionaries;
+@property (assign) NSArray *smsDictionaries;
+
+#pragma mark IMAGES
+@property (assign) UIImage *image;
+
+@end
399 ABContact.m
@@ -0,0 +1,399 @@
+/*
+ Erica Sadun, http://ericasadun.com
+ iPhone Developer's Cookbook, 3.0 Edition
+ BSD License, Use at your own risk
+ */
+
+#import "ABContact.h"
+#import "ABContactsHelper.h"
+
+@implementation ABContact
+@synthesize record;
+
+- (id) initWithRecord: (ABRecordRef) aRecord
+{
+ if (self = [super init]) record = aRecord;
+ return self;
+}
+
++ (id) contactWithRecord: (ABRecordRef) person
+{
+ return [[[ABContact alloc] initWithRecord:person] autorelease];
+}
+
++ (id) contact
+{
+ return [ABContact contactWithRecord:ABPersonCreate()];
+}
+
+- (void) dealloc
+{
+ if (record) CFRelease(record);
+ [super dealloc];
+}
+
+#pragma mark utilities
++ (NSString *) cleanLabel: (NSString *) aLabel
+{
+ return [[aLabel stringByReplacingOccurrencesOfString:@"_$!<" withString:@""] stringByReplacingOccurrencesOfString:@">!$_" withString:@""];
+}
+
++ (CFStringRef) formattedLabel: (NSString *) aLabel
+{
+ return (CFStringRef) [NSString stringWithFormat:@"_$!<%@>!$_", aLabel];
+}
+
++ (NSString *) localizedPropertyName: (ABPropertyID) aProperty
+{
+ NSString *propertyName = (NSString *)ABPersonCopyLocalizedPropertyName(aProperty);
+ return [propertyName autorelease];
+}
+
++ (ABPropertyType) propertyType: (ABPropertyID) aProperty
+{
+ return ABPersonGetTypeOfProperty(aProperty);
+}
+
++ (NSString *) propertyTypeString: (ABPropertyID) aProperty
+{
+ ABPropertyType ptype = ABPersonGetTypeOfProperty(aProperty);
+ if (ptype == kABInvalidPropertyType) return @"Invalid Property";
+ if (ptype == kABStringPropertyType) return @"String";
+ if (ptype == kABIntegerPropertyType) return @"Integer";
+ if (ptype == kABRealPropertyType) return @"Float";
+ if (ptype == kABDateTimePropertyType) return @"value";
+ if (ptype == kABDictionaryPropertyType) return @"Dictionary";
+ if (ptype == kABMultiStringPropertyType) return @"Multi String";
+ if (ptype == kABMultiIntegerPropertyType) return @"Multi Integer";
+ if (ptype == kABMultiRealPropertyType) return @"Multi Float";
+ if (ptype == kABMultiDateTimePropertyType) return @"Multi Date";
+ if (ptype == kABMultiDictionaryPropertyType) return @"Multi Dictionary";
+ return @"Invalid Property";
+}
+
++ (NSDictionary *) dictionaryWithValue: (id) value andLabel: (CFStringRef) label
+{
+ NSMutableDictionary *dict = [NSMutableDictionary dictionary];
+ if (value) [dict setObject:value forKey:@"value"];
+ if (label) [dict setObject:(NSString *)label forKey:@"label"];
+ return dict;
+}
+
++ (NSDictionary *) addressWithStreet: (NSString *) street withCity: (NSString *) city
+ withState:(NSString *) state withZip: (NSString *) zip
+ withCountry: (NSString *) country withCode: (NSString *) code
+{
+ NSMutableDictionary *md = [NSMutableDictionary dictionary];
+ if (street) [md setObject:street forKey:(NSString *) kABPersonAddressStreetKey];
+ if (city) [md setObject:city forKey:(NSString *) kABPersonAddressCityKey];
+ if (state) [md setObject:state forKey:(NSString *) kABPersonAddressStateKey];
+ if (zip) [md setObject:zip forKey:(NSString *) kABPersonAddressZIPKey];
+ if (country) [md setObject:country forKey:(NSString *) kABPersonAddressCountryKey];
+ if (code) [md setObject:code forKey:(NSString *) kABPersonAddressCountryCodeKey];
+ return md;
+}
+
++ (NSDictionary *) smsWithService: (CFStringRef) service andUser: (NSString *) userName
+{
+ NSMutableDictionary *sms = [NSMutableDictionary dictionary];
+ if (service) [sms setObject:(NSString *) service forKey:(NSString *) kABPersonInstantMessageServiceKey];
+ if (userName) [sms setObject:userName forKey:(NSString *) kABPersonInstantMessageUsernameKey];
+ return sms;
+}
+
+- (NSString *) removeSelfFromAddressBook
+{
+ // Record still exists after operation but is not in address book
+ // Fetch the record back to recover its proper id
+ ABAddressBookRef addressBook = ABAddressBookCreate();
+ CFErrorRef error;
+ BOOL success = ABAddressBookRemoveRecord(addressBook, self.record, &error);
+ if (!success) return [(NSError *)error localizedDescription];
+ success = ABAddressBookSave(addressBook, &error);
+ return success ? nil : [(NSError *)error localizedDescription];
+}
+
+#pragma mark Record ID and Type
+- (ABRecordID) recordID {return ABRecordGetRecordID(record);}
+- (ABRecordType) recordType {return ABRecordGetRecordType(record);}
+- (BOOL) isPerson {return self.recordType == kABPersonType;}
+
+#pragma mark Getting Single Value Strings
+- (NSString *) getRecordString:(ABPropertyID) anID
+{
+ return [(NSString *) ABRecordCopyValue(record, anID) autorelease];
+}
+- (NSString *) firstname {return [self getRecordString:kABPersonFirstNameProperty];}
+- (NSString *) lastname {return [self getRecordString:kABPersonLastNameProperty];}
+- (NSString *) middlename {return [self getRecordString:kABPersonMiddleNameProperty];}
+- (NSString *) prefix {return [self getRecordString:kABPersonPrefixProperty];}
+- (NSString *) suffix {return [self getRecordString:kABPersonSuffixProperty];}
+- (NSString *) nickname {return [self getRecordString:kABPersonNicknameProperty];}
+- (NSString *) firstnamephonetic {return [self getRecordString:kABPersonFirstNamePhoneticProperty];}
+- (NSString *) lastnamephonetic {return [self getRecordString:kABPersonLastNamePhoneticProperty];}
+- (NSString *) middlenamephonetic {return [self getRecordString:kABPersonMiddleNamePhoneticProperty];}
+- (NSString *) organization {return [self getRecordString:kABPersonOrganizationProperty];}
+- (NSString *) jobtitle {return [self getRecordString:kABPersonJobTitleProperty];}
+- (NSString *) department {return [self getRecordString:kABPersonDepartmentProperty];}
+- (NSString *) note {return [self getRecordString:kABPersonNoteProperty];}
+
+#pragma mark Contact Name Utility
+- (NSString *) contactName
+{
+ NSMutableString *string = [NSMutableString string];
+
+ if (self.firstname || self.lastname)
+ {
+ if (self.prefix) [string appendFormat:@"%@ ", self.prefix];
+ if (self.firstname) [string appendFormat:@"%@ ", self.firstname];
+ if (self.nickname) [string appendFormat:@"\"%@\" ", self.nickname];
+ if (self.lastname) [string appendFormat:@"%@", self.lastname];
+
+ if (self.suffix && string.length)
+ [string appendFormat:@", %@ ", self.suffix];
+ else
+ [string appendFormat:@" "];
+ }
+
+ if (self.organization) [string appendFormat:self.organization];
+
+ return string;
+}
+
+- (NSString *) compositeName
+{
+ NSString *string = (NSString *)ABRecordCopyCompositeName(record);
+ return [string autorelease];
+}
+
+#pragma mark Dates
+- (NSDate *) getRecordDate:(ABPropertyID) anID
+{
+ return [(NSDate *) ABRecordCopyValue(record, anID) autorelease];
+}
+
+- (NSDate *) birthday {return [self getRecordDate:kABPersonBirthdayProperty];}
+- (NSDate *) creationDate {return [self getRecordDate:kABPersonCreationDateProperty];}
+- (NSDate *) modificationDate {return [self getRecordDate:kABPersonModificationDateProperty];}
+
+#pragma mark Getting MultiValue Elements
+- (NSArray *) arrayForProperty: (ABPropertyID) anID
+{
+ CFTypeRef theProperty = ABRecordCopyValue(record, anID);
+ NSArray *items = (NSArray *)ABMultiValueCopyArrayOfAllValues(theProperty);
+ CFRelease(theProperty);
+ return [items autorelease];
+}
+
+- (NSArray *) labelsForProperty: (ABPropertyID) anID
+{
+ CFTypeRef theProperty = ABRecordCopyValue(record, anID);
+ NSMutableArray *labels = [NSMutableArray array];
+ for (int i = 0; i < ABMultiValueGetCount(theProperty); i++)
+ {
+ NSString *label = (NSString *)ABMultiValueCopyLabelAtIndex(theProperty, i);
+ [labels addObject:label];
+ [label release];
+ }
+ CFRelease(theProperty);
+ return labels;
+}
+
+- (NSArray *) emailArray {return [self arrayForProperty:kABPersonEmailProperty];}
+- (NSArray *) emailLabels {return [self labelsForProperty:kABPersonEmailProperty];}
+- (NSArray *) phoneArray {return [self arrayForProperty:kABPersonPhoneProperty];}
+- (NSArray *) phoneLabels {return [self labelsForProperty:kABPersonPhoneProperty];}
+- (NSArray *) relatedNameArray {return [self arrayForProperty:kABPersonRelatedNamesProperty];}
+- (NSArray *) relatedNameLabels {return [self labelsForProperty:kABPersonRelatedNamesProperty];}
+- (NSArray *) urlArray {return [self arrayForProperty:kABPersonURLProperty];}
+- (NSArray *) urlLabels {return [self labelsForProperty:kABPersonURLProperty];}
+- (NSArray *) dateArray {return [self arrayForProperty:kABPersonDateProperty];}
+- (NSArray *) dateLabels {return [self labelsForProperty:kABPersonDateProperty];}
+- (NSArray *) addressArray {return [self arrayForProperty:kABPersonAddressProperty];}
+- (NSArray *) addressLabels {return [self labelsForProperty:kABPersonAddressProperty];}
+- (NSArray *) smsArray {return [self arrayForProperty:kABPersonInstantMessageProperty];}
+- (NSArray *) smsLabels {return [self labelsForProperty:kABPersonInstantMessageProperty];}
+
+- (NSArray *) dictionaryArrayForProperty: (ABPropertyID) aProperty
+{
+ NSArray *valueArray = [self arrayForProperty:aProperty];
+ NSArray *labelArray = [self labelsForProperty:aProperty];
+
+ int num = MIN(valueArray.count, labelArray.count);
+ NSMutableArray *items = [NSMutableArray array];
+ for (int i = 0; i < num; i++)
+ {
+ NSMutableDictionary *md = [NSMutableDictionary dictionary];
+ [md setObject:[valueArray objectAtIndex:i] forKey:@"value"];
+ [md setObject:[labelArray objectAtIndex:i] forKey:@"label"];
+ [items addObject:md];
+ }
+ return items;
+}
+
+- (NSArray *) emailDictionaries
+{
+ return [self dictionaryArrayForProperty:kABPersonEmailProperty];
+}
+
+- (NSArray *) phoneDictionaries
+{
+ return [self dictionaryArrayForProperty:kABPersonPhoneProperty];
+}
+
+- (NSArray *) relatedNameDictionaries
+{
+ return [self dictionaryArrayForProperty:kABPersonRelatedNamesProperty];
+}
+
+- (NSArray *) urlDictionaries
+{
+ return [self dictionaryArrayForProperty:kABPersonURLProperty];
+}
+
+- (NSArray *) dateDictionaries
+{
+ return [self dictionaryArrayForProperty:kABPersonDateProperty];
+}
+
+- (NSArray *) addressDictionaries
+{
+ return [self dictionaryArrayForProperty:kABPersonAddressProperty];
+}
+
+- (NSArray *) smsDictionaries
+{
+ return [self dictionaryArrayForProperty:kABPersonInstantMessageProperty];
+}
+
+#pragma mark Setting Strings
+- (BOOL) setString: (NSString *) aString forProperty:(ABPropertyID) anID
+{
+ CFErrorRef error;
+ BOOL success = ABRecordSetValue(record, anID, (CFStringRef) aString, &error);
+ if (!success) NSLog(@"Error: %@", [(NSError *)error localizedDescription]);
+ return success;
+}
+
+- (void) setFirstname: (NSString *) aString {[self setString: aString forProperty: kABPersonFirstNameProperty];}
+- (void) setLastname: (NSString *) aString {[self setString: aString forProperty: kABPersonLastNameProperty];}
+- (void) setMiddlename: (NSString *) aString {[self setString: aString forProperty: kABPersonMiddleNameProperty];}
+- (void) setPrefix: (NSString *) aString {[self setString: aString forProperty: kABPersonPrefixProperty];}
+- (void) setSuffix: (NSString *) aString {[self setString: aString forProperty: kABPersonSuffixProperty];}
+- (void) setNickname: (NSString *) aString {[self setString: aString forProperty: kABPersonNicknameProperty];}
+- (void) setFirstnamephonetic: (NSString *) aString {[self setString: aString forProperty: kABPersonFirstNamePhoneticProperty];}
+- (void) setLastnamephonetic: (NSString *) aString {[self setString: aString forProperty: kABPersonLastNamePhoneticProperty];}
+- (void) setMiddlenamephonetic: (NSString *) aString {[self setString: aString forProperty: kABPersonMiddleNamePhoneticProperty];}
+- (void) setOrganization: (NSString *) aString {[self setString: aString forProperty: kABPersonOrganizationProperty];}
+- (void) setJobtitle: (NSString *) aString {[self setString: aString forProperty: kABPersonJobTitleProperty];}
+- (void) setDepartment: (NSString *) aString {[self setString: aString forProperty: kABPersonDepartmentProperty];}
+- (void) setNote: (NSString *) aString {[self setString: aString forProperty: kABPersonNoteProperty];}
+
+#pragma mark Setting MultiValue
+
+- (BOOL) setMulti: (ABMutableMultiValueRef) multi forProperty: (ABPropertyID) anID
+{
+ CFErrorRef error;
+ BOOL success = ABRecordSetValue(record, anID, multi, &error);
+ if (!success) NSLog(@"Error: %@", [(NSError *)error localizedDescription]);
+ return success;
+}
+- (ABMutableMultiValueRef) createMultiValueFromArray: (NSArray *) anArray withType: (ABPropertyType) aType
+{
+ ABMutableMultiValueRef multi = ABMultiValueCreateMutable(aType);
+ for (NSDictionary *dict in anArray)
+ ABMultiValueAddValueAndLabel(multi, (CFTypeRef) [dict objectForKey:@"value"], (CFTypeRef) [dict objectForKey:@"label"], NULL);
+ return multi;
+}
+
+- (void) setEmailDictionaries: (NSArray *) dictionaries
+{
+ // kABWorkLabel, kABHomeLabel, kABOtherLabel
+ ABMutableMultiValueRef multi = [self createMultiValueFromArray:dictionaries withType:kABMultiStringPropertyType];
+ [self setMulti:multi forProperty:kABPersonEmailProperty];
+}
+
+- (void) setPhoneDictionaries: (NSArray *) dictionaries
+{
+ // kABWorkLabel, kABHomeLabel, kABOtherLabel
+ // kABPersonPhoneMobileLabel, kABPersonPhoneIPhoneLabel, kABPersonPhoneMainLabel
+ // kABPersonPhoneHomeFAXLabel, kABPersonPhoneWorkFAXLabel, kABPersonPhonePagerLabel
+ ABMutableMultiValueRef multi = [self createMultiValueFromArray:dictionaries withType:kABMultiStringPropertyType];
+ [self setMulti:multi forProperty:kABPersonPhoneProperty];
+}
+
+- (void) setUrlDictionaries: (NSArray *) dictionaries
+{
+ // kABWorkLabel, kABHomeLabel, kABOtherLabel
+ // kABPersonHomePageLabel
+ ABMutableMultiValueRef multi = [self createMultiValueFromArray:dictionaries withType:kABMultiStringPropertyType];
+ [self setMulti:multi forProperty:kABPersonURLProperty];
+}
+
+// Not used/shown on iPhone
+- (void) setRelatedNameDictionaries: (NSArray *) dictionaries
+{
+ // kABWorkLabel, kABHomeLabel, kABOtherLabel
+ // kABPersonMotherLabel, kABPersonFatherLabel, kABPersonParentLabel,
+ // kABPersonSisterLabel, kABPersonBrotherLabel, kABPersonChildLabel,
+ // kABPersonFriendLabel, kABPersonSpouseLabel, kABPersonPartnerLabel,
+ // kABPersonManagerLabel, kABPersonAssistantLabel
+ ABMutableMultiValueRef multi = [self createMultiValueFromArray:dictionaries withType:kABMultiStringPropertyType];
+ [self setMulti:multi forProperty:kABPersonRelatedNamesProperty];
+}
+
+- (void) setDateDictionaries: (NSArray *) dictionaries
+{
+ // kABWorkLabel, kABHomeLabel, kABOtherLabel
+ // kABPersonAnniversaryLabel
+ ABMutableMultiValueRef multi = [self createMultiValueFromArray:dictionaries withType:kABMultiDateTimePropertyType];
+ [self setMulti:multi forProperty:kABPersonDateProperty];
+}
+
+- (void) setAddressDictionaries: (NSArray *) dictionaries
+{
+ // kABPersonAddressStreetKey, kABPersonAddressCityKey, kABPersonAddressStateKey
+ // kABPersonAddressZIPKey, kABPersonAddressCountryKey, kABPersonAddressCountryCodeKey
+ ABMutableMultiValueRef multi = [self createMultiValueFromArray:dictionaries withType:kABMultiDictionaryPropertyType];
+ [self setMulti:multi forProperty:kABPersonAddressProperty];
+}
+
+- (void) setSmsDictionaries: (NSArray *) dictionaries
+{
+ // kABWorkLabel, kABHomeLabel, kABOtherLabel,
+ // kABPersonInstantMessageServiceKey, kABPersonInstantMessageUsernameKey
+ // kABPersonInstantMessageServiceYahoo, kABPersonInstantMessageServiceJabber
+ // kABPersonInstantMessageServiceMSN, kABPersonInstantMessageServiceICQ
+ // kABPersonInstantMessageServiceAIM,
+ ABMutableMultiValueRef multi = [self createMultiValueFromArray:dictionaries withType:kABMultiDictionaryPropertyType];
+ [self setMulti:multi forProperty:kABPersonInstantMessageProperty];
+}
+
+#pragma mark Images
+- (UIImage *) image
+{
+ if (!ABPersonHasImageData(record)) return nil;
+ CFDataRef imageData = ABPersonCopyImageData(record);
+ UIImage *image = [UIImage imageWithData:(NSData *) imageData];
+ CFRelease(imageData);
+ return image;
+}
+
+- (void) setImage: (UIImage *) image
+{
+ CFErrorRef error;
+ BOOL success;
+
+ if (image == nil) // remove
+ {
+ if (!ABPersonHasImageData(record)) return; // no image to remove
+ success = ABPersonRemoveImageData(record, &error);
+ if (!success) NSLog(@"Error: %@", [(NSError *)error localizedDescription]);
+ return;
+ }
+
+ NSData *data = UIImagePNGRepresentation(image);
+ success = ABPersonSetImageData(record, (CFDataRef) data, &error);
+ if (!success) NSLog(@"Error: %@", [(NSError *)error localizedDescription]);
+}
+@end
39 ABContactsHelper.h
@@ -0,0 +1,39 @@
+/*
+ Erica Sadun, http://ericasadun.com
+ iPhone Developer's Cookbook, 3.0 Edition
+ BSD License, Use at your own risk
+ */
+
+#import <UIKit/UIKit.h>
+#import <AddressBook/AddressBook.h>
+#import <AddressBookUI/AddressBookUI.h>
+#import "ABContact.h"
+
+@interface ABContactsHelper : NSObject
+
+// Address Book Contacts
++ (NSArray *) contacts;
++ (NSArray *) groups;
++ (NSArray *) people;
+
+// Counting
++ (int) contactsCount;
++ (int) contactsWithImageCount;
++ (int) contactsWithoutImageCount;
+
+// Sorting
++ (BOOL) firstNameSorting;
+
+// Add contacts
++ (NSString *) addContact: (ABContact *) aContact;
+
+// Find contacts
++ (ABContact *) contactWithID: (ABRecordID) aRecordID;
++ (NSArray *) contactsMatchingName: (NSString *) fname;
++ (NSArray *) contactsMatchingName: (NSString *) fname andName: (NSString *) lname;
+@end
+
+// For the simple utility of it. Feel free to comment out if desired
+@interface NSString (cstring)
+@property (readonly) char *UTF8String;
+@end
104 ABContactsHelper.m
@@ -0,0 +1,104 @@
+/*
+ Erica Sadun, http://ericasadun.com
+ iPhone Developer's Cookbook, 3.0 Edition
+ BSD License, Use at your own risk
+ */
+
+#import "ABContactsHelper.h"
+
+@implementation ABContactsHelper
++ (NSArray *) contacts
+{
+ NSMutableArray *array = [NSMutableArray array];
+ ABAddressBookRef addressBook = ABAddressBookCreate();
+ NSArray *thePeople = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
+ for (id person in thePeople)
+ [array addObject:[ABContact contactWithRecord:(ABRecordRef)person]];
+ [thePeople release];
+ return array;
+}
+
++ (NSArray *) people
+{
+ NSArray *contacts = [ABContactsHelper contacts];
+ NSPredicate *pred = [NSPredicate predicateWithFormat:@"recordType == %d", kABPersonType];
+ return [contacts filteredArrayUsingPredicate:pred];
+}
+
++ (NSArray *) groups
+{
+ NSArray *contacts = [ABContactsHelper contacts];
+ NSPredicate *pred = [NSPredicate predicateWithFormat:@"recordType == %d", kABGroupType];
+ return [contacts filteredArrayUsingPredicate:pred];
+}
+
++ (int) contactsCount
+{
+ ABAddressBookRef addressBook = ABAddressBookCreate();
+ return ABAddressBookGetPersonCount(addressBook);
+}
+
++ (int) contactsWithImageCount
+{
+ ABAddressBookRef addressBook = ABAddressBookCreate();
+ NSArray *peopleArray = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
+ int ncount = 0;
+ for (id person in peopleArray) if (ABPersonHasImageData(person)) ncount++;
+ [peopleArray release];
+ return ncount;
+}
+
++ (int) contactsWithoutImageCount
+{
+ ABAddressBookRef addressBook = ABAddressBookCreate();
+ NSArray *peopleArray = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
+ int ncount = 0;
+ for (id person in peopleArray) if (!ABPersonHasImageData(person)) ncount++;
+ [peopleArray release];
+ return ncount;
+}
+
+// Sorting
++ (BOOL) firstNameSorting
+{
+ return (ABPersonGetCompositeNameFormat() == kABPersonCompositeNameFormatFirstNameFirst);
+}
+
+#pragma mark Contact Management
++ (NSString *) addContact: (ABContact *) aContact
+{
+ ABAddressBookRef addressBook = ABAddressBookCreate();
+ CFErrorRef error;
+ BOOL success = ABAddressBookAddRecord(addressBook, aContact.record, &error);
+ if (!success) return [(NSError *)error localizedDescription];
+ success = ABAddressBookSave(addressBook, &error);
+ return success ? nil : [(NSError *)error localizedDescription];
+}
+
++ (ABContact *) contactWithID: (ABRecordID) aRecordID
+{
+ NSArray *contacts = [ABContactsHelper contacts];
+ NSPredicate *pred = [NSPredicate predicateWithFormat:@"recordID == %d", aRecordID];
+ NSArray *results = [contacts filteredArrayUsingPredicate:pred];
+ return results.count ? [results lastObject] : nil;
+}
+
++ (NSArray *) contactsMatchingName: (NSString *) fname
+{
+ NSPredicate *pred;
+ NSArray *contacts = [ABContactsHelper contacts];
+ pred = [NSPredicate predicateWithFormat:@"firstname contains[cd] %@ OR lastname contains[cd] %@ OR nickname contains[cd] %@ OR middlename contains[cd] %@", fname, fname, fname, fname];
+ return [contacts filteredArrayUsingPredicate:pred];
+}
+
++ (NSArray *) contactsMatchingName: (NSString *) fname andName: (NSString *) lname
+{
+ NSPredicate *pred;
+ NSArray *contacts = [ABContactsHelper contacts];
+ pred = [NSPredicate predicateWithFormat:@"firstname contains[cd] %@ OR lastname contains[cd] %@ OR nickname contains[cd] %@ OR middlename contains[cd] %@", fname, fname, fname, fname];
+ contacts = [contacts filteredArrayUsingPredicate:pred];
+ pred = [NSPredicate predicateWithFormat:@"firstname contains[cd] %@ OR lastname contains[cd] %@ OR nickname contains[cd] %@ OR middlename contains[cd] %@", lname, lname, lname, lname];
+ contacts = [contacts filteredArrayUsingPredicate:pred];
+ return contacts;
+}
+@end
BIN  Default.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
263 HelloWorld.xcodeproj/project.pbxproj
@@ -0,0 +1,263 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1D3623EC0D0F72F000981E51 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */; };
+ 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
+ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
+ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
+ 8E3A1F090FAA199F009B0518 /* cover320x416.png in Resources */ = {isa = PBXBuildFile; fileRef = 8E3A1F080FAA199F009B0518 /* cover320x416.png */; };
+ 8E4156E90FA4EE0E0006D27C /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 8E4156E70FA4EE0E0006D27C /* Default.png */; };
+ 8E4156EA0FA4EE0E0006D27C /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 8E4156E80FA4EE0E0006D27C /* icon.png */; };
+ 8E785FCB0FCDB853006EA81F /* TestBedViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8E785FCA0FCDB853006EA81F /* TestBedViewController.xib */; };
+ 8EE3297D103C8A9400FBD34F /* ABContactsHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EE3297C103C8A9400FBD34F /* ABContactsHelper.m */; };
+ 8EE329C7103C928500FBD34F /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8EE329C5103C928500FBD34F /* AddressBook.framework */; };
+ 8EE329C8103C928500FBD34F /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8EE329C6103C928500FBD34F /* AddressBookUI.framework */; };
+ 8EE32C92103CE3CD00FBD34F /* ABContact.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EE32C91103CE3CD00FBD34F /* ABContact.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 1D6058910D05DD3D006BFB54 /* HelloWorld.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloWorld.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 32CA4F630368D1EE00C91783 /* HelloWorld_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HelloWorld_Prefix.pch; sourceTree = "<group>"; };
+ 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 8E3A1F080FAA199F009B0518 /* cover320x416.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = cover320x416.png; sourceTree = "<group>"; };
+ 8E4156E70FA4EE0E0006D27C /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; };
+ 8E4156E80FA4EE0E0006D27C /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = "<group>"; };
+ 8E785FCA0FCDB853006EA81F /* TestBedViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TestBedViewController.xib; sourceTree = "<group>"; };
+ 8EE3297B103C8A9400FBD34F /* ABContactsHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABContactsHelper.h; sourceTree = "<group>"; };
+ 8EE3297C103C8A9400FBD34F /* ABContactsHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ABContactsHelper.m; sourceTree = "<group>"; };
+ 8EE329C5103C928500FBD34F /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = "../Work/SDKStuff/99BOOK/C09 - PeoplePlacesThings/01a - Finding People/iphoneos2.0/System/Library/Frameworks/AddressBook.framework"; sourceTree = SOURCE_ROOT; };
+ 8EE329C6103C928500FBD34F /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = "../Work/SDKStuff/99BOOK/C09 - PeoplePlacesThings/01a - Finding People/iphoneos2.0/System/Library/Frameworks/AddressBookUI.framework"; sourceTree = SOURCE_ROOT; };
+ 8EE32C90103CE3CD00FBD34F /* ABContact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABContact.h; sourceTree = "<group>"; };
+ 8EE32C91103CE3CD00FBD34F /* ABContact.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ABContact.m; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 1D60588F0D05DD3D006BFB54 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,
+ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
+ 1D3623EC0D0F72F000981E51 /* CoreGraphics.framework in Frameworks */,
+ 8EE329C7103C928500FBD34F /* AddressBook.framework in Frameworks */,
+ 8EE329C8103C928500FBD34F /* AddressBookUI.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 19C28FACFE9D520D11CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 1D6058910D05DD3D006BFB54 /* HelloWorld.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
+ isa = PBXGroup;
+ children = (
+ 8EE32C90103CE3CD00FBD34F /* ABContact.h */,
+ 8EE32C91103CE3CD00FBD34F /* ABContact.m */,
+ 29B97316FDCFA39411CA2CEA /* main.m */,
+ 8EE3297B103C8A9400FBD34F /* ABContactsHelper.h */,
+ 8EE3297C103C8A9400FBD34F /* ABContactsHelper.m */,
+ 8EB688610FA64AD100489E4B /* Support */,
+ 29B97323FDCFA39411CA2CEA /* Frameworks */,
+ 19C28FACFE9D520D11CA2CBB /* Products */,
+ );
+ name = CustomTemplate;
+ sourceTree = "<group>";
+ };
+ 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 8EE329C5103C928500FBD34F /* AddressBook.framework */,
+ 8EE329C6103C928500FBD34F /* AddressBookUI.framework */,
+ 1D3623EB0D0F72F000981E51 /* CoreGraphics.framework */,
+ 1D30AB110D05D00D00671497 /* Foundation.framework */,
+ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 8EB688610FA64AD100489E4B /* Support */ = {
+ isa = PBXGroup;
+ children = (
+ 8E785FCA0FCDB853006EA81F /* TestBedViewController.xib */,
+ 8E3A1F080FAA199F009B0518 /* cover320x416.png */,
+ 32CA4F630368D1EE00C91783 /* HelloWorld_Prefix.pch */,
+ 8D1107310486CEB800E47090 /* Info.plist */,
+ 8E4156E80FA4EE0E0006D27C /* icon.png */,
+ 8E4156E70FA4EE0E0006D27C /* Default.png */,
+ );
+ name = Support;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 1D6058900D05DD3D006BFB54 /* HelloWorld */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "HelloWorld" */;
+ buildPhases = (
+ 1D60588D0D05DD3D006BFB54 /* Resources */,
+ 1D60588E0D05DD3D006BFB54 /* Sources */,
+ 1D60588F0D05DD3D006BFB54 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = HelloWorld;
+ productName = HelloWorld;
+ productReference = 1D6058910D05DD3D006BFB54 /* HelloWorld.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 29B97313FDCFA39411CA2CEA /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "HelloWorld" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 1D6058900D05DD3D006BFB54 /* HelloWorld */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 1D60588D0D05DD3D006BFB54 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8E4156E90FA4EE0E0006D27C /* Default.png in Resources */,
+ 8E4156EA0FA4EE0E0006D27C /* icon.png in Resources */,
+ 8E3A1F090FAA199F009B0518 /* cover320x416.png in Resources */,
+ 8E785FCB0FCDB853006EA81F /* TestBedViewController.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 1D60588E0D05DD3D006BFB54 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1D60589B0D05DD56006BFB54 /* main.m in Sources */,
+ 8EE3297D103C8A9400FBD34F /* ABContactsHelper.m in Sources */,
+ 8EE32C92103CE3CD00FBD34F /* ABContact.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1D6058940D05DD3E006BFB54 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Erica Sadun";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/../Work/SDKStuff/99BOOK/C09 - PeoplePlacesThings/01a - Finding People/iphoneos2.0/System/Library/Frameworks\"",
+ );
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = HelloWorld_Prefix.pch;
+ INFOPLIST_FILE = Info.plist;
+ PREBINDING = NO;
+ PRODUCT_NAME = HelloWorld;
+ };
+ name = Debug;
+ };
+ 1D6058950D05DD3E006BFB54 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)/../Work/SDKStuff/99BOOK/C09 - PeoplePlacesThings/01a - Finding People/iphoneos2.0/System/Library/Frameworks\"",
+ );
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = HelloWorld_Prefix.pch;
+ INFOPLIST_FILE = Info.plist;
+ PREBINDING = NO;
+ PRODUCT_NAME = HelloWorld;
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+ C01FCF4F08A954540054247B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ CODE_SIGN_IDENTITY = "Erica Sadun";
+ "CODE_SIGN_IDENTITY[sdk=iphonesimulator*]" = "iPhone Developer";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ PRODUCT_NAME = "Oh Hello";
+ SDKROOT = iphoneos2.0;
+ };
+ name = Debug;
+ };
+ C01FCF5008A954540054247B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ PREBINDING = NO;
+ SDKROOT = iphoneos2.0;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "HelloWorld" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1D6058940D05DD3E006BFB54 /* Debug */,
+ 1D6058950D05DD3E006BFB54 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ C01FCF4E08A954540054247B /* Build configuration list for PBXProject "HelloWorld" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4F08A954540054247B /* Debug */,
+ C01FCF5008A954540054247B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
8 HelloWorld_Prefix.pch
@@ -0,0 +1,8 @@
+//
+// Prefix header for all source files of the 'HelloWorld' target in the 'HelloWorld' project
+//
+
+#ifdef __OBJC__
+ #import <Foundation/Foundation.h>
+ #import <UIKit/UIKit.h>
+#endif
26 Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.sadun.${EXECUTABLE_NAME}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+</dict>
+</plist>
223 TestBedViewController.xib
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.03">
+ <data>
+ <int key="IBDocument.SystemTarget">768</int>
+ <string key="IBDocument.SystemVersion">9J61</string>
+ <string key="IBDocument.InterfaceBuilderVersion">680</string>
+ <string key="IBDocument.AppKitVersion">949.46</string>
+ <string key="IBDocument.HIToolboxVersion">353.00</string>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="35"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="372490531">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ </object>
+ <object class="IBProxyObject" id="843779117">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ </object>
+ <object class="IBUIView" id="440620744">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">292</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUIImageView" id="1064941195">
+ <reference key="NSNextResponder" ref="440620744"/>
+ <int key="NSvFlags">256</int>
+ <string key="NSFrameSize">{320, 416}</string>
+ <reference key="NSSuperview" ref="440620744"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <int key="IBUIContentMode">4</int>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ <object class="NSCustomResource" key="IBUIImage">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">cover320x416.png</string>
+ </object>
+ </object>
+ <object class="IBUITextView" id="311618606">
+ <reference key="NSNextResponder" ref="440620744"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrameSize">{320, 279}</string>
+ <reference key="NSSuperview" ref="440620744"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ <bool key="IBUIShowsHorizontalScrollIndicator">NO</bool>
+ <bool key="IBUIDelaysContentTouches">NO</bool>
+ <bool key="IBUICanCancelContentTouches">NO</bool>
+ <bool key="IBUIBouncesZoom">NO</bool>
+ <bool key="IBUIEditable">NO</bool>
+ <string key="IBUIText"/>
+ <object class="IBUITextInputTraits" key="IBUITextInputTraits">
+ <int key="IBUIAutocapitalizationType">2</int>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{320, 416}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ <object class="NSColorSpace" key="NSCustomColorSpace">
+ <int key="NSID">2</int>
+ </object>
+ </object>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+ <object class="IBUISimulatedNavigationBarMetrics" key="IBUISimulatedTopBarMetrics">
+ <bool key="IBUIPrompted">NO</bool>
+ </object>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">view</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="440620744"/>
+ </object>
+ <int key="connectionID">33</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">textView</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="311618606"/>
+ </object>
+ <int key="connectionID">36</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <object class="NSArray" key="object" id="884947135">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="372490531"/>
+ <reference key="parent" ref="884947135"/>
+ <string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="843779117"/>
+ <reference key="parent" ref="884947135"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">32</int>
+ <reference key="object" ref="440620744"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1064941195"/>
+ <reference ref="311618606"/>
+ </object>
+ <reference key="parent" ref="884947135"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">34</int>
+ <reference key="object" ref="1064941195"/>
+ <reference key="parent" ref="440620744"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">35</int>
+ <reference key="object" ref="311618606"/>
+ <reference key="parent" ref="440620744"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>32.IBEditorWindowLastContentRect</string>
+ <string>32.IBPluginDependency</string>
+ <string>35.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>TestBedViewController</string>
+ <string>UIResponder</string>
+ <string>{{21, 492}, {320, 480}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">36</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">TestBedViewController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSMutableArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>textView</string>
+ <string>view</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UITextView</string>
+ <string>UIView</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBUserSource</string>
+ <string key="minorKey"/>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.LastKnownRelativeProjectPath">HelloWorld.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">3.1</string>
+ </data>
+</archive>
BIN  cover320x416.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 do-git
@@ -0,0 +1,15 @@
+#! /bin/csh -f
+
+if ($#argv != 1) then
+ echo "Usage $0 commit-message"
+ exit 1
+endif
+
+cp ../UIDevice/*.[hm] .
+rm -rf build
+rm .DS_Store
+rm */.DS_Store
+rm -rf *.xcodeproj/ericasadun.*
+git add -A
+git commit -m "$1"
+git push
BIN  icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
146 main.m
@@ -0,0 +1,146 @@
+/*
+ Erica Sadun, http://ericasadun.com
+ iPhone Developer's Cookbook, 3.0 Edition
+ BSD License, Use at your own risk
+ */
+
+#import <UIKit/UIKit.h>
+#import "ABContactsHelper.h"
+
+#define COOKBOOK_PURPLE_COLOR [UIColor colorWithRed:0.20392f green:0.19607f blue:0.61176f alpha:1.0f]
+#define BARBUTTON(TITLE, SELECTOR) [[[UIBarButtonItem alloc] initWithTitle:TITLE style:UIBarButtonItemStylePlain target:self action:SELECTOR] autorelease]
+
+@interface TestBedViewController : UIViewController
+{
+ NSMutableString *log;
+ IBOutlet UITextView *textView;
+}
+@property (retain) NSMutableString *log;
+@property (retain) UITextView *textView;
+@end
+
+@implementation TestBedViewController
+@synthesize log;
+@synthesize textView;
+
+- (void) doLog: (NSString *) formatstring, ...
+{
+ va_list arglist;
+ if (!formatstring) return;
+ va_start(arglist, formatstring);
+ NSString *outstring = [[[NSString alloc] initWithFormat:formatstring arguments:arglist] autorelease];
+ va_end(arglist);
+ [self.log appendString:outstring];
+ [self.log appendString:@"\n"];
+ self.textView.text = self.log;
+}
+
+- (void) addGW
+{
+ // Search for a contact, creating a new one if one is not found
+ NSArray *contacts = [ABContactsHelper contactsMatchingName:@"Washington" andName:@"George"];
+ printf("%d matching contacts found\n", contacts.count);
+ ABContact *peep = contacts.count ? [contacts lastObject] : [ABContact contact];
+
+ if (contacts.count) [peep removeSelfFromAddressBook]; // remove in preparation to update contact
+ printf("Record %d\n", peep.recordID);
+
+ // Person basic string information (see full list in ABContact)
+ peep.firstname = @"George";
+ peep.lastname = @"Washington";
+ peep.nickname = @"Prez";
+ peep.firstnamephonetic = @"Horhay";
+ peep.lastnamephonetic = @"Warsh-ing-town";
+ peep.jobtitle = @"President of the United States of America";
+
+ // Emails
+ NSMutableArray *emailarray = [NSMutableArray array];
+ [emailarray addObject:[ABContact dictionaryWithValue:@"george@home.com" andLabel:kABHomeLabel]];
+ [emailarray addObject:[ABContact dictionaryWithValue:@"george@work.com" andLabel:kABWorkLabel]];
+ [emailarray addObject:[ABContact dictionaryWithValue:@"george@gmail.com" andLabel:(CFStringRef) @"Google"]];
+ peep.emailDictionaries = emailarray;
+
+ // Phones
+ NSMutableArray *phonearray = [NSMutableArray array];
+ [phonearray addObject:[ABContact dictionaryWithValue:@"202-555-1212" andLabel:kABPersonPhoneMainLabel]];
+ [phonearray addObject:[ABContact dictionaryWithValue:@"202-555-1313" andLabel:(CFStringRef) @"Google"]];
+ [phonearray addObject:[ABContact dictionaryWithValue:@"202-555-1414" andLabel:kABPersonPhoneMobileLabel]];
+ peep.phoneDictionaries = phonearray;
+
+ // URLS
+ NSMutableArray *urls = [NSMutableArray array];
+ [urls addObject:[ABContact dictionaryWithValue:@"http://whitehouse.org" andLabel:kABPersonHomePageLabel]];
+ [urls addObject:[ABContact dictionaryWithValue:@"http://en.wikipedia.org/wiki/Washington" andLabel:kABOtherLabel]];
+ peep.urlDictionaries = urls;
+
+ // Dates
+ NSMutableArray *dates = [NSMutableArray array];
+ [dates addObject:[ABContact dictionaryWithValue:[NSDate dateWithTimeIntervalSinceNow:0] andLabel:(CFStringRef) @"Anniversary"]];
+ peep.dateDictionaries = dates;
+
+ // Addresses
+ NSDictionary *addy = [ABContact addressWithStreet:@"1600 Pennsylvania Avenue" withCity:@"Arlington" withState:@"Virginia" withZip:@"20202" withCountry:nil withCode:nil];
+ NSMutableArray *addies = [NSMutableArray array];
+ [addies addObject:[ABContact dictionaryWithValue:addy andLabel:kABHomeLabel]];
+ peep.addressDictionaries = addies;
+
+ // SMSes
+ NSDictionary *sms = [ABContact smsWithService:kABPersonInstantMessageServiceAIM andUser:@"geow1735"];
+ NSMutableArray *smses = [NSMutableArray array];
+ [smses addObject:[ABContact dictionaryWithValue:sms andLabel:kABWorkLabel]];
+ peep.smsDictionaries = smses;
+
+ // Relationships (Not actually used on the iPhone, but here for the sake of example)
+ NSMutableArray *relatedarray = [NSMutableArray array];
+ [relatedarray addObject:[ABContact dictionaryWithValue:@"Ethel Washington" andLabel:kABPersonMotherLabel]];
+ peep.relatedNameDictionaries = relatedarray;
+
+ [ABContactsHelper addContact:peep]; // save to address book
+}
+
+- (void) scan
+{
+ for (ABContact *person in [ABContactsHelper people])
+ {
+ printf("******\n");
+ printf("Name: %s\n", person.compositeName.UTF8String);
+ printf("Organization: %s\n", person.organization.UTF8String);
+ printf("Title: %s\n", person.jobtitle.UTF8String);
+ printf("Department: %s\n", person.department.UTF8String);
+ printf("Note: %s\n", person.note.UTF8String);
+ printf("Creation Date: %s\n", [person.creationDate description].UTF8String);
+ printf("Modification Date: %s\n", [person.modificationDate description].UTF8String);
+ printf("Emails: %s\n", [person.emailDictionaries description].UTF8String);
+ printf("Phones: %s\n", [person.phoneDictionaries description].UTF8String);
+ printf("URLs: %s\n", [person.urlDictionaries description].UTF8String);
+ printf("Addresses: %s\n\n", [person.addressDictionaries description].UTF8String);
+ }
+}
+
+- (void) viewDidLoad
+{
+ self.navigationController.navigationBar.tintColor = COOKBOOK_PURPLE_COLOR;
+ self.navigationItem.rightBarButtonItem = BARBUTTON(@"Add GW", @selector(addGW));
+ self.navigationItem.leftBarButtonItem = BARBUTTON(@"Scan", @selector(scan));
+}
+@end
+
+@interface TestBedAppDelegate : NSObject <UIApplicationDelegate>
+@end
+
+@implementation TestBedAppDelegate
+- (void)applicationDidFinishLaunching:(UIApplication *)application {
+ UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+ UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[[TestBedViewController alloc] init]];
+ [window addSubview:nav.view];
+ [window makeKeyAndVisible];
+}
+@end
+
+int main(int argc, char *argv[])
+{
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+ int retVal = UIApplicationMain(argc, argv, nil, @"TestBedAppDelegate");
+ [pool release];
+ return retVal;
+}
Please sign in to comment.
Something went wrong with that request. Please try again.