Permalink
Browse files

Added Groups

  • Loading branch information...
1 parent 520eda4 commit cd1416d86b6a856d41cff2b3b9d0c087cf63d64a Erica Sadun committed Aug 21, 2009
Showing with 256 additions and 11 deletions.
  1. +2 −1 ABContact.h
  2. +21 −0 ABContact.m
  3. +8 −2 ABContactsHelper.h
  4. +33 −5 ABContactsHelper.m
  5. +33 −0 ABGroup.h
  6. +112 −0 ABGroup.m
  7. +6 −0 HelloWorld.xcodeproj/project.pbxproj
  8. +41 −3 main.m
View
@@ -16,6 +16,7 @@
// Convenience allocation methods
+ (id) contact;
+ (id) contactWithRecord: (ABRecordRef) record;
++ (id) contactWithRecordID: (ABRecordID) recordID;
// Class utility methods
+ (NSString *) localizedPropertyName: (ABPropertyID) aProperty;
@@ -60,7 +61,7 @@
@property (nonatomic, readonly) NSString *compositeName; // via AB
#pragma mark DATE
-@property (nonatomic, readonly) NSDate *birthday;
+@property (nonatomic, assign) NSDate *birthday;
@property (nonatomic, readonly) NSDate *creationDate;
@property (nonatomic, readonly) NSDate *modificationDate;
View
@@ -22,6 +22,15 @@ + (id) contactWithRecord: (ABRecordRef) person
return [[[ABContact alloc] initWithRecord:person] autorelease];
}
++ (id) contactWithRecordID: (ABRecordID) recordID
+{
+ ABAddressBookRef addressBook = ABAddressBookCreate();
+ ABRecordRef contactrec = ABAddressBookGetPersonWithRecordID(addressBook, recordID);
+ ABContact *contact = [self contactWithRecord:contactrec];
+ CFRelease(contactrec);
+ return contact;
+}
+
// Thanks to Ciaran
+ (id) contact
{
@@ -387,6 +396,18 @@ - (void) setJobtitle: (NSString *) aString {[self setString: aString forProperty
- (void) setDepartment: (NSString *) aString {[self setString: aString forProperty: kABPersonDepartmentProperty];}
- (void) setNote: (NSString *) aString {[self setString: aString forProperty: kABPersonNoteProperty];}
+#pragma mark Setting Dates
+
+- (BOOL) setDate: (NSDate *) aDate forProperty:(ABPropertyID) anID
+{
+ CFErrorRef error;
+ BOOL success = ABRecordSetValue(record, anID, (CFDateRef) aDate, &error);
+ if (!success) NSLog(@"Error: %@", [(NSError *)error localizedDescription]);
+ return success;
+}
+
+- (void) setBirthday: (NSDate *) aDate {[self setDate: aDate forProperty: kABPersonBirthdayProperty];}
+
#pragma mark Setting MultiValue
- (BOOL) setMulti: (ABMutableMultiValueRef) multi forProperty: (ABPropertyID) anID
View
@@ -8,28 +8,34 @@
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
#import "ABContact.h"
+#import "ABGroup.h"
@interface ABContactsHelper : NSObject
// Address Book Contacts
+ (NSArray *) contacts; // people
++ (NSArray *) groups; // groups
// Counting
+ (int) contactsCount;
+ (int) contactsWithImageCount;
+ (int) contactsWithoutImageCount;
++ (int) numberOfGroups;
// Sorting
+ (BOOL) firstNameSorting;
-// Add contacts
+// Add contacts and groups
+ (BOOL) addContact: (ABContact *) aContact withError: (NSError **) error;
++ (BOOL) addGroup: (ABGroup *) aGroup withError: (NSError **) error;
// Find contacts
-+ (ABContact *) contactWithID: (ABRecordID) aRecordID;
+ (NSArray *) contactsMatchingName: (NSString *) fname;
+ (NSArray *) contactsMatchingName: (NSString *) fname andName: (NSString *) lname;
+ (NSArray *) contactsMatchingPhone: (NSString *) number;
+
+// Find groups
++ (NSArray *) groupsMatchingName: (NSString *) fname;
@end
// For the simple utility of it. Feel free to comment out if desired
View
@@ -48,6 +48,27 @@ + (int) contactsWithoutImageCount
return ncount;
}
+// Groups
++ (int) numberOfGroups
+{
+ ABAddressBookRef addressBook = ABAddressBookCreate();
+ NSArray *groups = (NSArray *)ABAddressBookCopyArrayOfAllGroups(addressBook);
+ int ncount = groups.count;
+ [groups release];
+ return ncount;
+}
+
++ (NSArray *) groups
+{
+ ABAddressBookRef addressBook = ABAddressBookCreate();
+ NSArray *groups = (NSArray *)ABAddressBookCopyArrayOfAllGroups(addressBook);
+ NSMutableArray *array = [NSMutableArray arrayWithCapacity:groups.count];
+ for (id group in groups)
+ [array addObject:[ABGroup groupWithRecord:(ABRecordRef)group]];
+ [groups release];
+ return array;
+}
+
// Sorting
+ (BOOL) firstNameSorting
{
@@ -64,12 +85,11 @@ + (BOOL) addContact: (ABContact *) aContact withError: (NSError **) error
return ABAddressBookSave(addressBook, (CFErrorRef *) error);
}
-+ (ABContact *) contactWithID: (ABRecordID) aRecordID
++ (BOOL) addGroup: (ABGroup *) aGroup withError: (NSError **) error
{
- NSArray *contacts = [ABContactsHelper contacts];
- NSPredicate *pred = [NSPredicate predicateWithFormat:@"recordID == %d", aRecordID];
- NSArray *results = [contacts filteredArrayUsingPredicate:pred];
- return results.count ? [results lastObject] : nil;
+ ABAddressBookRef addressBook = ABAddressBookCreate();
+ if (!ABAddressBookAddRecord(addressBook, aGroup.record, (CFErrorRef *) error)) return NO;
+ return ABAddressBookSave(addressBook, (CFErrorRef *) error);
}
+ (NSArray *) contactsMatchingName: (NSString *) fname
@@ -98,4 +118,12 @@ + (NSArray *) contactsMatchingPhone: (NSString *) number
pred = [NSPredicate predicateWithFormat:@"phonenumbers contains[cd] %@", number];
return [contacts filteredArrayUsingPredicate:pred];
}
+
++ (NSArray *) groupsMatchingName: (NSString *) fname
+{
+ NSPredicate *pred;
+ NSArray *groups = [ABContactsHelper groups];
+ pred = [NSPredicate predicateWithFormat:@"name contains[cd] %@ ", fname];
+ return [groups filteredArrayUsingPredicate:pred];
+}
@end
View
@@ -0,0 +1,33 @@
+/*
+ Erica Sadun, http://ericasadun.com
+ iPhone Developer's Cookbook, 3.0 Edition
+ BSD License, Use at your own risk
+ */
+
+#import <AddressBook/AddressBook.h>
+#import <AddressBookUI/AddressBookUI.h>
+#import "ABContact.h"
+
+@interface ABGroup : NSObject
+{
+ ABRecordRef record;
+}
+
++ (id) group;
++ (id) groupWithRecord: (ABRecordRef) record;
++ (id) groupWithRecordID: (ABRecordID) recordID;
+- (BOOL) removeSelfFromAddressBook: (NSError **) error;
+
+@property (nonatomic, readonly) ABRecordRef record;
+@property (nonatomic, readonly) ABRecordID recordID;
+@property (nonatomic, readonly) ABRecordType recordType;
+@property (nonatomic, readonly) BOOL isPerson;
+
+- (NSArray *) membersWithSorting: (ABPersonSortOrdering) ordering;
+- (BOOL) addMember: (ABContact *) contact withError: (NSError **) error;
+- (BOOL) removeMember: (ABContact *) contact withError: (NSError **) error;
+
+@property (nonatomic, assign) NSString *name;
+@property (nonatomic, readonly) NSArray *members;
+
+@end
View
@@ -0,0 +1,112 @@
+/*
+ Erica Sadun, http://ericasadun.com
+ iPhone Developer's Cookbook, 3.0 Edition
+ BSD License, Use at your own risk
+ */
+
+#import "ABGroup.h"
+#import "ABContactsHelper.h"
+
+@implementation ABGroup
+@synthesize record;
+
+// Thanks to Quentarez, Ciaran
+- (id) initWithRecord: (ABRecordRef) aRecord
+{
+ if (self = [super init]) record = CFRetain(aRecord);
+ return self;
+}
+
++ (id) groupWithRecord: (ABRecordRef) grouprec
+{
+ return [[[ABGroup alloc] initWithRecord:grouprec] autorelease];
+}
+
++ (id) groupWithRecordID: (ABRecordID) recordID
+{
+ ABAddressBookRef addressBook = ABAddressBookCreate();
+ ABRecordRef grouprec = ABAddressBookGetGroupWithRecordID(addressBook, recordID);
+ ABGroup *group = [self groupWithRecord:grouprec];
+ CFRelease(grouprec);
+ return group;
+}
+
+// Thanks to Ciaran
++ (id) group
+{
+ ABRecordRef grouprec = ABGroupCreate();
+ id group = [ABGroup groupWithRecord:grouprec];
+ CFRelease(grouprec);
+ return group;
+}
+
+- (void) dealloc
+{
+ if (record) CFRelease(record);
+ [super dealloc];
+}
+
+- (BOOL) removeSelfFromAddressBook: (NSError **) error
+{
+ ABAddressBookRef addressBook = ABAddressBookCreate();
+ if (!ABAddressBookRemoveRecord(addressBook, self.record, (CFErrorRef *) error)) return NO;
+ return ABAddressBookSave(addressBook, (CFErrorRef *) error);
+}
+
+#pragma mark Record ID and Type
+- (ABRecordID) recordID {return ABRecordGetRecordID(record);}
+- (ABRecordType) recordType {return ABRecordGetRecordType(record);}
+- (BOOL) isPerson {return self.recordType == kABPersonType;}
+
+#pragma mark management
+- (NSArray *) members
+{
+ NSArray *contacts = (NSArray *)ABGroupCopyArrayOfAllMembers(self.record);
+ NSMutableArray *array = [NSMutableArray arrayWithCapacity:contacts.count];
+ for (id contact in contacts)
+ [array addObject:[ABContact contactWithRecord:(ABRecordRef)contact]];
+ [contacts release];
+ return array;
+}
+
+// kABPersonSortByFirstName = 0, kABPersonSortByLastName = 1
+- (NSArray *) membersWithSorting: (ABPersonSortOrdering) ordering
+{
+ NSArray *contacts = (NSArray *)ABGroupCopyArrayOfAllMembersWithSortOrdering(self.record, ordering);
+ NSMutableArray *array = [NSMutableArray arrayWithCapacity:contacts.count];
+ for (id contact in contacts)
+ [array addObject:[ABContact contactWithRecord:(ABRecordRef)contact]];
+ [contacts release];
+ return array;
+}
+
+- (BOOL) addMember: (ABContact *) contact withError: (NSError **) error
+{
+ return ABGroupAddMember(self.record, contact.record, (CFErrorRef *) error);
+}
+
+- (BOOL) removeMember: (ABContact *) contact withError: (NSError **) error
+{
+ return ABGroupRemoveMember(self.record, contact.record, (CFErrorRef *) error);
+}
+
+#pragma mark name
+
+- (NSString *) getRecordString:(ABPropertyID) anID
+{
+ return [(NSString *) ABRecordCopyValue(record, anID) autorelease];
+}
+
+- (NSString *) name
+{
+ NSString *string = (NSString *)ABRecordCopyCompositeName(record);
+ return [string autorelease];
+}
+
+- (void) setName: (NSString *) aString
+{
+ CFErrorRef error;
+ BOOL success = ABRecordSetValue(record, kABGroupNameProperty, (CFStringRef) aString, &error);
+ if (!success) NSLog(@"Error: %@", [(NSError *)error localizedDescription]);
+}
+@end
@@ -14,6 +14,7 @@
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 */; };
+ 8E6DF3F0103F101E00E12A1D /* ABGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E6DF3EF103F101E00E12A1D /* ABGroup.m */; };
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 */; };
@@ -32,6 +33,8 @@
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>"; };
+ 8E6DF3EE103F101E00E12A1D /* ABGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABGroup.h; sourceTree = "<group>"; };
+ 8E6DF3EF103F101E00E12A1D /* ABGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ABGroup.m; 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>"; };
@@ -68,6 +71,8 @@
29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
isa = PBXGroup;
children = (
+ 8E6DF3EE103F101E00E12A1D /* ABGroup.h */,
+ 8E6DF3EF103F101E00E12A1D /* ABGroup.m */,
8EE32C90103CE3CD00FBD34F /* ABContact.h */,
8EE32C91103CE3CD00FBD34F /* ABContact.m */,
29B97316FDCFA39411CA2CEA /* main.m */,
@@ -164,6 +169,7 @@
1D60589B0D05DD56006BFB54 /* main.m in Sources */,
8EE3297D103C8A9400FBD34F /* ABContactsHelper.m in Sources */,
8EE32C92103CE3CD00FBD34F /* ABContact.m in Sources */,
+ 8E6DF3F0103F101E00E12A1D /* ABGroup.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
@@ -146,13 +146,51 @@ - (void) scan
printf("******\n");
printf("Name: %s\n", person.contactName.UTF8String);
}
-}
+}
+
+- (void) viewgroups
+{
+ printf("There are %d groups\n", [ABContactsHelper numberOfGroups]);
+ for (ABGroup *group in [ABContactsHelper groups])
+ {
+ printf("Name: %s\n", group.name.UTF8String);
+ NSArray *members = group.members;
+ printf("Members: %d\n", members.count);
+
+ int n = 1;
+ for (ABContact *contact in members)
+ printf("%d: %s\n", n++, contact.compositeName.UTF8String);
+ }
+}
+
+- (void) addGroup
+{
+ NSArray *groups = [ABContactsHelper groupsMatchingName:@"Everyone"];
+ printf("%d matching groups found\n", groups.count);
+ ABGroup *group = groups.count ? [groups lastObject] : [ABGroup group];
+
+ // Remove existing group to allow modification
+ if (groups.count) [group removeSelfFromAddressBook:nil];
+
+ // set name
+ group.name = @"Everyone";
+
+ // add members
+ NSArray *contacts = [ABContactsHelper contacts];
+ for (ABContact *contact in contacts)
+ [group addMember:contact withError:nil];
+
+ // Save the new or modified group
+ [ABContactsHelper addGroup:group withError:nil];
+}
- (void) viewDidLoad
{
self.navigationController.navigationBar.tintColor = COOKBOOK_PURPLE_COLOR;
- self.navigationItem.rightBarButtonItem = BARBUTTON(@"Add GW", @selector(addGW));
- self.navigationItem.leftBarButtonItem = BARBUTTON(@"Scan", @selector(scan));
+ // self.navigationItem.rightBarButtonItem = BARBUTTON(@"Add GW", @selector(addGW));
+ self.navigationItem.rightBarButtonItem = BARBUTTON(@"Groups", @selector(viewgroups));
+ // self.navigationItem.leftBarButtonItem = BARBUTTON(@"Scan", @selector(scan));
+ self.navigationItem.leftBarButtonItem = BARBUTTON(@"Add", @selector(addGroup));
}
@end

0 comments on commit cd1416d

Please sign in to comment.