blob: 7ef250d4e7f63ac5757fe60b261a60c69ee3d319 [file] [log] [blame]
//
// GTMABAddressBook.h
//
// Copyright 2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
// These classes wrap up the iPhone AddressBook 'C' API in a manner very
// similar to that found on Mac OS X. They differ only in that none of these
// routines throws, and some of the types are different as necessitated by
// the APIs that they wrap. These wrappers also protect you from a number
// of issues in the AddressBook API (as of iPhone SDK 2.0/2.1)
//
// Note that there is a strings file that you may want to localize
// (GTMABAddressBook.strings).
//
// If things seem strange, it may be due to one of the following radars:
// 6240394 AddressBook framework constants not initialized until
// ABCreateAddressBook called
// -- CLOSED as designed
// 6208390 Integer and real values don't work in ABMultiValueRefs
// (and this isn't part of the title, but dictionaries don't work
// either)
// 6207605 RecordIDs for people and groups are not unique in AddressBook
// -- CLOSED as designed
// 6204021 kABGroupNameProperty and kABPersonFirstNameProperty have the same
// value
// 6203982 ABPersonCopyLocalizedPropertyName returns name for
// kABGroupNameProperty
// 6203961 ABPersonGetTypeOfProperty returns a type for kABGroupNameProperty
// 6203854 ABMultiValues hash to their address
// 6203836 ABRecords hash to their address
// -- CLOSED behaves correctly
// 6203606 Need CFTypeIDs for AddressBook CFTypes
// 6202868 ABPersonSetImageData should validate image data
// 6202860 Passing nil person into ABGroupAddMember crashes
// -- CLOSED behaves correctly
// 6202827 Passing nil info ABMultiValueAddValueAndLabel causes crash
// -- CLOSED behaves correctly
// 6202807 ABMultiValueInsertValueAndLabelAtIndex allows you to insert values
// past end
// 6201276 Removing a NULL record using ABAddressBookRemoveRecord crashes
// -- CLOSED behaves correctly
// 6201258 Adding a NULL record using ABAddressBookAddRecord crashes
// -- CLOSED behaves correctly
// 6201046 ABRecordSetValue returns true even if you pass in a bad type for a
// value
// 6201005 ABRecordRemoveValue returns true for value that aren't in the record
// -- CLOSED behaves correctly
// 6200703 ABAddressBookAddRecord doesn't add an item to the people array until
// it's saved
// 6200638 ABAddressBookHasUnsavedChanges doesn't work
// -- CLOSED fixed in iOS 3.2
#import "GTMDefines.h"
#import <Foundation/Foundation.h>
#if GTM_IPHONE_SDK
#import <AddressBook/AddressBook.h>
@class UIImage;
#else // GTM_IPHONE_SDK
#import <AddressBook/AddressBook.h>
#import <AddressBook/ABAddressBookC.h>
@class NSImage;
#endif // GTM_IPHONE_SDK
@class GTMABPerson;
@class GTMABGroup;
@class GTMABRecord;
GTM_EXTERN NSString *const kGTMABUnknownPropertyName;
#if GTM_IPHONE_SDK
@class UIImage;
typedef ABRecordID GTMABRecordID;
typedef ABPropertyID GTMABPropertyID;
typedef UIImage GTMABImage;
typedef ABPersonCompositeNameFormat GTMABPersonCompositeNameFormat;
typedef ABMultiValueIdentifier GTMABMultiValueIdentifier;
enum _GTMABPropertyType {
kGTMABInvalidPropertyType = kABInvalidPropertyType,
kGTMABStringPropertyType = kABStringPropertyType,
kGTMABIntegerPropertyType = kABIntegerPropertyType,
kGTMABRealPropertyType = kABRealPropertyType,
kGTMABDateTimePropertyType = kABDateTimePropertyType,
kGTMABDictionaryPropertyType = kABDictionaryPropertyType,
kGTMABMultiStringPropertyType = kABMultiStringPropertyType,
kGTMABMultiIntegerPropertyType = kABMultiIntegerPropertyType,
kGTMABMultiRealPropertyType = kABMultiRealPropertyType,
kGTMABMultiDateTimePropertyType = kABMultiDateTimePropertyType,
kGTMABMultiDictionaryPropertyType = kABMultiDictionaryPropertyType,
};
typedef ABPropertyType GTMABPropertyType;
#define kGTMABPersonFirstNameProperty kABPersonFirstNameProperty
#define kGTMABPersonLastNameProperty kABPersonLastNameProperty
#define kGTMABPersonBirthdayProperty kABPersonBirthdayProperty
#define kGTMABPersonPhoneProperty kABPersonPhoneProperty
#define kGTMABGroupNameProperty kABGroupNameProperty
#define kGTMABPersonPhoneMainLabel ((NSString *)kABPersonPhoneMainLabel)
#define kGTMABPersonPhoneMobileLabel ((NSString *)kABPersonPhoneMobileLabel)
#define kGTMABPersonPhoneHomeLabel ((NSString *)kABHomeLabel)
#define kGTMABPersonPhoneWorkLabel ((NSString *)kABWorkLabel)
#define kGTMABPersonPhoneWorkFaxLabel ((NSString *)kABPersonPhoneWorkFAXLabel)
#define kGTMABPersonPhoneHomeFaxLabel ((NSString *)kABPersonPhoneHomeFAXLabel)
#define kGTMABPersonPhonePagerLabel ((NSString *)kABPersonPhonePagerLabel)
#define kGTMABOtherLabel ((NSString *)kABOtherLabel)
#define kGTMABMultiValueInvalidIdentifier kABMultiValueInvalidIdentifier
#define kGTMABRecordInvalidID kABRecordInvalidID
#else // GTM_IPHONE_SDK
@class NSImage;
typedef NSString* GTMABRecordID;
typedef NSString* GTMABPropertyID;
typedef NSString* GTMABMultiValueIdentifier;
typedef NSImage GTMABImage;
typedef uint32_t GTMABPersonCompositeNameFormat;
enum {
kABPersonCompositeNameFormatFirstNameFirst = 0,
kABPersonCompositeNameFormatLastNameFirst = 1
};
enum _GTMABPropertyType {
kGTMABInvalidPropertyType = kABErrorInProperty,
kGTMABStringPropertyType = kABStringProperty,
kGTMABIntegerPropertyType = kABIntegerProperty,
kGTMABRealPropertyType = kABRealProperty,
kGTMABDateTimePropertyType = kABDateProperty,
kGTMABDictionaryPropertyType = kABDictionaryProperty,
kGTMABMultiStringPropertyType = kABMultiStringProperty,
kGTMABMultiIntegerPropertyType = kABMultiIntegerProperty,
kGTMABMultiRealPropertyType = kABMultiRealProperty,
kGTMABMultiDateTimePropertyType = kABMultiDateProperty,
kGTMABMultiDictionaryPropertyType = kABMultiDictionaryProperty,
};
typedef CFIndex GTMABPropertyType;
#define kGTMABPersonFirstNameProperty kABFirstNameProperty
#define kGTMABPersonLastNameProperty kABLastNameProperty
#define kGTMABPersonBirthdayProperty kABBirthdayProperty
#define kGTMABPersonPhoneProperty kABPhoneProperty
#define kGTMABGroupNameProperty kABGroupNameProperty
#define kGTMABPersonPhoneMainLabel kABPhoneMainLabel
#define kGTMABPersonPhoneMobileLabel kABPhoneMobileLabel
#define kGTMABPersonPhoneHomeLabel kABPhoneHomeLabel
#define kGTMABPersonPhoneWorkLabel kABPhoneWorkLabel
#define kGTMABPersonPhoneWorkFaxLabel kABPhoneWorkFAXLabel
#define kGTMABPersonPhoneHomeFaxLabel kABPhoneHomeFAXLabel
#define kGTMABPersonPhonePagerLabel kABPhonePagerLabel
#define kGTMABOtherLabel kABOtherLabel
#define kGTMABMultiValueInvalidIdentifier @"ABMultiValueInvalidIdentifier"
#define kGTMABRecordInvalidID @"ABRecordInvalidID"
extern NSString* const kABPersonRecordType;
extern NSString* const kABGroupRecordType;
#endif // GTM_IPHONE_SDK
// Wrapper for an AddressBook on iPhone
@interface GTMABAddressBook : NSObject {
@private
ABAddressBookRef addressBook_;
}
// Returns a new instance of an address book.
+ (GTMABAddressBook *)addressBook;
// Return the address book reference
- (ABAddressBookRef)addressBookRef;
// Saves changes made since the last save
// Return YES if successful (or there was no change)
- (BOOL)save;
// Returns YES if there are unsaved changes
// The unsaved changes flag is automatically set when changes are made
// As of iPhone 2.1, this does not work, and will always return NO.
// Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work
- (BOOL)hasUnsavedChanges;
// Returns a GTMABPerson matching an ID
// Returns nil if the record could not be found
- (GTMABPerson *)personForId:(GTMABRecordID)uniqueId;
// Returns a GTMABGroup matching an ID
// Returns nil if the record could not be found
- (GTMABGroup *)groupForId:(GTMABRecordID)uniqueId;
// Adds a record (ABPerson or ABGroup) to the AddressBook database
// Be sure to read notes for -people and -group.
- (BOOL)addRecord:(GTMABRecord *)record;
// Removes a record (ABPerson or ABGroup) from the AddressBook database
- (BOOL)removeRecord:(GTMABRecord *)record;
// Returns an array (GTMABPerson) of all the people in the AddressBook database
// As of iPhone 2.1, this array will not contain new entries until you save
// the address book.
// Radar 6200703: ABAddressBookAddRecord doesn't add an item to the people array
// until it's saved
- (NSArray *)people;
// Returns an array of all the groups (GTMABGroup) in the AddressBook database
// As of iPhone 2.1, this array will not contain new entries until you save
// the address book.
// Radar 6200703: ABAddressBookAddRecord doesn't add an item to the people array
// until it's saved
- (NSArray *)groups;
// Performs a prefix search on the composite names of people in an address book
// and returns an array of persons that match the search criteria.
// Ignores case.
- (NSArray *)peopleWithCompositeNameWithPrefix:(NSString *)prefix;
// Performs a prefix search on the composite names of groups in an address book
// and returns an array of groups that match the search criteria.
// Ignores case.
- (NSArray *)groupsWithCompositeNameWithPrefix:(NSString *)prefix;
// Returns a localized name for a given label
+ (NSString *)localizedLabel:(NSString *)label;
@end
// Wrapper for a ABRecord on iPhone.
// A abstract class. Instantiate one of the concrete subclasses, GTMABPerson or
// GTMABGroup.
@interface GTMABRecord : NSObject {
@private
ABRecordRef record_;
}
// Create a record with a recordRef.
// Since GTMABRecord is an abstract base class, attempting to create one
// of these directly will throw an exception. Use with one of the concrete
// subclasses.
+ (id)recordWithRecord:(ABRecordRef)record;
// Designated initializer
// Since GTMABRecord is an abstract base class, attempting to create one
// of these directly will throw an exception. Use with one of the concrete
// subclasses.
- (id)initWithRecord:(ABRecordRef)record;
// Return our recordRef
- (ABRecordRef)recordRef;
// Return the recordID for the record
- (GTMABRecordID)recordID;
// Returns the value of a given property.
// The type of the value depends on the property type.
- (id)valueForProperty:(GTMABPropertyID)property;
// Set the value of a given property.
// The type of the value must match the property type.
// Returns YES if value set properly
- (BOOL)setValue:(id)value forProperty:(GTMABPropertyID)property;
// Removes the value for the property
// Returns yes if value removed
- (BOOL)removeValueForProperty:(GTMABPropertyID)property;
// returns a human friendly name for the record
- (NSString *)compositeName;
// returns the type of a property
+ (GTMABPropertyType)typeOfProperty:(GTMABPropertyID)property;
// returns a human friendly localized name for a property
+ (NSString *)localizedPropertyName:(GTMABPropertyID)property;
@end
// Wrapper for an ABPerson on iPhone
@interface GTMABPerson : GTMABRecord
// Creates a person with a first name and a last name.
+ (GTMABPerson *)personWithFirstName:(NSString *)first
lastName:(NSString *)last;
// Sets image data for a person. Data must be to a block of data that
// will create a valid GTMABImage.
- (BOOL)setImageData:(NSData *)data;
// Returns the image data.
- (NSData *)imageData;
// Returns the image for a person
- (GTMABImage *)image;
// Sets a the image for a person
- (BOOL)setImage:(GTMABImage *)image;
// Returns the format in with names are composited
+ (GTMABPersonCompositeNameFormat)compositeNameFormat;
@end
// Wrapper for a ABGroup on iPhone
@interface GTMABGroup : GTMABRecord
// Create a new group named |name|
+ (GTMABGroup *)groupNamed:(NSString *)name;
// Return an array of members (GTMABPerson)
- (NSArray *)members;
// Add a member to a group
- (BOOL)addMember:(GTMABPerson *)person;
// Remove a member from a group
- (BOOL)removeMember:(GTMABPerson *)person;
@end
// GTMABMultiValue does not support NSFastEnumeration because in
// the Apple frameworks it returns identifiers which are already NSStrings.
// In our case identifiers aren't NS types, and it doesn't make sense
// to convert them to NSNumbers just to convert them back so you can
// actually get at the values and labels.
// Instead we supply valueEnumerator and labelEnumerator which you can
// fast enumerate on to get values and labels directly.
@interface GTMABMultiValue : NSObject <NSCopying, NSMutableCopying> {
@protected
ABMultiValueRef multiValue_;
}
// Create a multi value
- (id)initWithMultiValue:(ABMultiValueRef)multiValue;
// return it's ref
- (ABMultiValueRef)multiValueRef;
// Returns the number of value/label pairs
- (NSUInteger)count;
// Returns a value at a given index
// Returns nil if index is out of bounds
- (id)valueAtIndex:(NSUInteger)idx;
// Returns a label at a given index
// Returns nil if index is out of bounds
- (NSString *)labelAtIndex:(NSUInteger)idx;
// Returns an identifier at a given index
// Returns kABMultiValueInvalidIdentifier if index is out of bounds
- (GTMABMultiValueIdentifier)identifierAtIndex:(NSUInteger)idx;
// Returns the index of a given identifier
// Returns NSNotFound if not found
- (NSUInteger)indexForIdentifier:(GTMABMultiValueIdentifier)identifier;
// Type of the contents of this multivalue
- (GTMABPropertyType)propertyType;
// Returns the value for a given identifier
// Returns nil if the identifier is not found
- (id)valueForIdentifier:(GTMABMultiValueIdentifier)identifier;
// Returns the value for a given identifier
// Returns nil if the identifier is not found
- (NSString *)labelForIdentifier:(GTMABMultiValueIdentifier)identifier;
// Returns an enumerator for enumerating through values
- (NSEnumerator *)valueEnumerator;
// Returns an enumerator for enumerating through labels
- (NSEnumerator *)labelEnumerator;
@end
@interface GTMABMutableMultiValue : GTMABMultiValue {
@private
// Use unsigned long here instead of NSUInteger because that's what
// NSFastEnumeration Protocol wants currently (iPhone 2.1)
unsigned long mutations_;
}
// Create a new mutable multivalue with a given type
+ (id)valueWithPropertyType:(GTMABPropertyType)type;
// Create a new mutable multivalue with a given type
- (id)initWithPropertyType:(GTMABPropertyType)type;
// Create a new mutable multivalue based on |multiValue|
- (id)initWithMutableMultiValue:(ABMutableMultiValueRef)multiValue;
// Adds a value with its label
// Returns the identifier if successful, kABMultiValueInvalidIdentifier
// otherwise.
- (GTMABMultiValueIdentifier)addValue:(id)value withLabel:(CFStringRef)label;
// Insert a value/label pair at a given index
// Returns the identifier if successful. kABMultiValueInvalidIdentifier
// otherwise
// If index is out of bounds, returns kABMultiValueInvalidIdentifier.
- (GTMABMultiValueIdentifier)insertValue:(id)value
withLabel:(CFStringRef)label
atIndex:(NSUInteger)index;
// Removes a value/label pair at a given index
// Returns NO if index out of bounds
- (BOOL)removeValueAndLabelAtIndex:(NSUInteger)index;
// Replaces a value at a given index
// Returns NO if index out of bounds
- (BOOL)replaceValueAtIndex:(NSUInteger)index withValue:(id)value;
// Replaces a label at a given index
// Returns NO if index out of bounds
- (BOOL)replaceLabelAtIndex:(NSUInteger)index withLabel:(CFStringRef)label;
@end