aboutsummaryrefslogtreecommitdiff
path: root/iPhone
diff options
context:
space:
mode:
authorGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2010-08-31 13:06:43 +0000
committerGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2010-08-31 13:06:43 +0000
commit721e03bf2cf93584569ae1200a6a4d50d536d105 (patch)
tree021f0ab822b370065f04e069cf817e0f69941696 /iPhone
parent62962eac5b57c2a5990bfb34f397e972b69e0490 (diff)
[Author: thomasvl]
Removed iPhone/GTMABAddressBook in favor of AddressBook/GTMABAddressBook. Removed Foundation/GTMHTTPServer and UnitTesting/GTMTestHTTPServer, they are going to go live with the fetcher used by GData (since they were done for that testing). Removed Foundation/GTMBase64 and Foundation/GTMNSData+Hex in favor of Foundation/GTMStringEncoding. R=dmaclach DELTA=5118 (13 added, 5105 deleted, 0 changed)
Diffstat (limited to 'iPhone')
-rw-r--r--iPhone/GTMABAddressBook.h328
-rw-r--r--iPhone/GTMABAddressBook.m901
-rw-r--r--iPhone/GTMABAddressBook.stringsbin1428 -> 0 bytes
-rw-r--r--iPhone/GTMABAddressBookTest.m608
4 files changed, 0 insertions, 1837 deletions
diff --git a/iPhone/GTMABAddressBook.h b/iPhone/GTMABAddressBook.h
deleted file mode 100644
index 828f05a..0000000
--- a/iPhone/GTMABAddressBook.h
+++ /dev/null
@@ -1,328 +0,0 @@
-//
-// 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
-
-#import <UIKit/UIKit.h>
-#import <AddressBook/AddressBook.h>
-#import "GTMDefines.h"
-
-#if !GTM_IPHONE_SDK
-#error This file is for iPhone use only use ABAddressBook on Mac OS X
-#endif
-
-@class GTMABPerson;
-@class GTMABGroup;
-@class GTMABRecord;
-
-GTM_EXTERN NSString *const kGTMABUnknownPropertyName;
-
-// 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;
-
-// Saves changes made since the last save
-// Return YES if successful (or there was no change)
-- (BOOL)saveAndReturnError:(NSError **)error;
-
-// 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;
-
-// Reverts any changes that have been made and resets the unsaved flag
-// Be sure to read notes for -hasUnsavedChanges and -people and -groups.
-- (void)revert;
-
-// Returns a GTMABPerson matching an ID
-// Returns nil if the record could not be found
-- (GTMABPerson *)personForId:(ABRecordID)uniqueId;
-
-// Returns a GTMABGroup matching an ID
-// Returns nil if the record could not be found
-- (GTMABGroup *)groupForId:(ABRecordID)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;
-
-// Returns a localized name for a given label
-+ (NSString *)localizedLabel:(CFStringRef)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
-- (ABRecordID)recordID;
-
-// Returns the value of a given property.
-// The type of the value depends on the property type.
-- (id)valueForProperty:(ABPropertyID)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:(ABPropertyID)property;
-
-// Removes the value for the property
-// Returns yes if value removed
-- (BOOL)removeValueForProperty:(ABPropertyID)property;
-
-// returns a human friendly name for the record
-- (NSString *)compositeName;
-
-// returns the type of a property
-+ (ABPropertyType)typeOfProperty:(ABPropertyID)property;
-
-// returns a human friendly localized name for a property
-+ (NSString *)localizedPropertyName:(ABPropertyID)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 UIImage.
-- (BOOL)setImageData:(NSData *)data;
-
-// Returns the image data.
-- (NSData *)imageData;
-
-// Returns the image for a person
-- (UIImage *)image;
-
-// Sets a the image for a person
-- (BOOL)setImage:(UIImage *)image;
-
-// Returns the format in with names are composited
-+ (ABPersonCompositeNameFormat)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 supprt 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
-- (ABMultiValueIdentifier)identifierAtIndex:(NSUInteger)idx;
-
-// Returns the index of a given identifier
-// Returns NSNotFound if not found
-- (NSUInteger)indexForIdentifier:(ABMultiValueIdentifier)identifier;
-
-// Type of the contents of this multivalue
-- (ABPropertyType)propertyType;
-
-// Returns the value for a given identifier
-// Returns nil if the identifier is not found
-- (id)valueForIdentifier:(ABMultiValueIdentifier)identifier;
-
-// Returns the value for a given identifier
-// Returns nil if the identifier is not found
-- (NSString *)labelForIdentifier:(ABMultiValueIdentifier)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:(ABPropertyType)type;
-
-// Create a new mutable multivalue with a given type
-- (id)initWithPropertyType:(ABPropertyType)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.
-- (ABMultiValueIdentifier)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.
-- (ABMultiValueIdentifier)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
diff --git a/iPhone/GTMABAddressBook.m b/iPhone/GTMABAddressBook.m
deleted file mode 100644
index bb84e61..0000000
--- a/iPhone/GTMABAddressBook.m
+++ /dev/null
@@ -1,901 +0,0 @@
-//
-// GTMAddressBook.m
-//
-// 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.
-//
-
-#import "GTMABAddressBook.h"
-#import "GTMGarbageCollection.h"
-
-NSString *const kGTMABUnknownPropertyName = @"UNKNOWN_PROPERTY";
-
-typedef struct {
- ABPropertyType pType;
- Class class;
-} TypeClassNameMap;
-
-@interface GTMABMultiValue ()
-- (unsigned long*)mutations;
-@end
-
-@interface GTMABMutableMultiValue ()
-// Checks to see if a value is a valid type to be stored in this multivalue
-- (BOOL)checkValueType:(id)value;
-@end
-
-@interface GTMABMultiValueEnumerator : NSEnumerator {
- @private
- __weak ABMultiValueRef ref_; // ref_ cached from enumeree_
- GTMABMultiValue *enumeree_;
- unsigned long mutations_;
- NSUInteger count_;
- NSUInteger index_;
- BOOL useLabels_;
-}
-+ (id)valueEnumeratorFor:(GTMABMultiValue*)enumeree;
-+ (id)labelEnumeratorFor:(GTMABMultiValue*)enumeree;
-- (id)initWithEnumeree:(GTMABMultiValue*)enumeree useLabels:(BOOL)useLabels;
-- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
- objects:(id *)stackbuf
- count:(NSUInteger)len;
-@end
-
-@implementation GTMABAddressBook
-+ (GTMABAddressBook *)addressBook {
- return [[[self alloc] init] autorelease];
-}
-
-- (id)init {
- if ((self = [super init])) {
- addressBook_ = ABAddressBookCreate();
- if (!addressBook_) {
- // COV_NF_START
- [self release];
- self = nil;
- // COV_NF_END
- }
- }
- return self;
-}
-
-- (void)dealloc {
- if (addressBook_) {
- CFRelease(addressBook_);
- }
- [super dealloc];
-}
-
-- (BOOL)save {
- return [self saveAndReturnError:NULL];
-}
-
-- (BOOL)saveAndReturnError:(NSError **)error {
- CFErrorRef cfError = NULL;
- bool wasGood = ABAddressBookSave(addressBook_, &cfError);
- GTMCFAutorelease(cfError);
- if (error) {
- *error = (NSError *)cfError; // COV_NF_LINE
- }
- return wasGood ? YES : NO;
-}
-
-- (BOOL)hasUnsavedChanges {
- return ABAddressBookHasUnsavedChanges(addressBook_);
-}
-
-- (void)revert {
- ABAddressBookRevert(addressBook_);
-}
-
-- (BOOL)addRecord:(GTMABRecord *)record {
- // Note: we check for bad data here because of radar
- // 6201258 Adding a NULL record using ABAddressBookAddRecord crashes
- if (!record) return NO;
- CFErrorRef cfError = NULL;
- bool wasGood = ABAddressBookAddRecord(addressBook_,
- [record recordRef], &cfError);
- if (cfError) {
- // COV_NF_START
- _GTMDevLog(@"Error in [%@ %@]: %@",
- [self class], NSStringFromSelector(_cmd), cfError);
- CFRelease(cfError);
- // COV_NF_END
- }
- return wasGood ? YES : NO;
-}
-
-- (BOOL)removeRecord:(GTMABRecord *)record {
- // Note: we check for bad data here because of radar
- // 6201276 Removing a NULL record using ABAddressBookRemoveRecord crashes
- if (!record) return NO;
- CFErrorRef cfError = NULL;
- bool wasGood = ABAddressBookRemoveRecord(addressBook_,
- [record recordRef], &cfError);
- if (cfError) {
- // COV_NF_START
- _GTMDevLog(@"Error in [%@ %@]: %@",
- [self class], NSStringFromSelector(_cmd), cfError);
- CFRelease(cfError);
- // COV_NF_END
- }
- return wasGood ? YES : NO;
-}
-
-- (NSArray *)people {
- NSArray *people
- = GTMCFAutorelease(ABAddressBookCopyArrayOfAllPeople(addressBook_));
- NSMutableArray *result = [NSMutableArray arrayWithCapacity:[people count]];
- for (id person in people) {
- [result addObject:[GTMABPerson recordWithRecord:person]];
- }
- return result;
-}
-
-- (NSArray *)groups {
- NSArray *groups
- = GTMCFAutorelease(ABAddressBookCopyArrayOfAllGroups(addressBook_));
- NSMutableArray *result = [NSMutableArray arrayWithCapacity:[groups count]];
- for (id group in groups) {
- [result addObject:[GTMABGroup recordWithRecord:group]];
- }
- return result;
-}
-
-- (ABAddressBookRef)addressBookRef {
- return addressBook_;
-}
-
-- (GTMABPerson *)personForId:(ABRecordID)uniqueId {
- GTMABPerson *person = nil;
- ABRecordRef ref = ABAddressBookGetPersonWithRecordID(addressBook_, uniqueId);
- if (ref) {
- person = [GTMABPerson recordWithRecord:ref];
- }
- return person;
-}
-
-- (GTMABGroup *)groupForId:(ABRecordID)uniqueId {
- GTMABGroup *group = nil;
- ABRecordRef ref = ABAddressBookGetGroupWithRecordID(addressBook_, uniqueId);
- if (ref) {
- group = [GTMABGroup recordWithRecord:ref];
- }
- return group;
-}
-
-+ (NSString *)localizedLabel:(CFStringRef)label {
- return GTMCFAutorelease(ABAddressBookCopyLocalizedLabel(label));
-}
-
-@end
-
-@implementation GTMABRecord
-+ (id)recordWithRecord:(ABRecordRef)record {
- return [[[self alloc] initWithRecord:record] autorelease];
-}
-
-- (id)initWithRecord:(ABRecordRef)record {
- if ((self = [super init])) {
- if ([self class] == [GTMABRecord class]) {
- [self autorelease];
- [self doesNotRecognizeSelector:_cmd];
- }
- if (!record) {
- [self release];
- self = nil;
- } else {
- record_ = CFRetain(record);
- }
- }
- return self;
-}
-
-- (NSUInteger)hash {
- // This really isn't completely valid due to
- // 6203836 ABRecords hash to their address
- // but it's the best we can do without knowing what properties
- // are in a record, and we don't have an API for that.
- return CFHash(record_);
-}
-
-- (BOOL)isEqual:(id)object {
- // This really isn't completely valid due to
- // 6203836 ABRecords hash to their address
- // but it's the best we can do without knowing what properties
- // are in a record, and we don't have an API for that.
- return [object respondsToSelector:@selector(recordRef)]
- && CFEqual(record_, [object recordRef]);
-}
-
-- (void)dealloc {
- if (record_) {
- CFRelease(record_);
- }
- [super dealloc];
-}
-
-- (ABRecordRef)recordRef {
- return record_;
-}
-
-- (ABRecordID)recordID {
- return ABRecordGetRecordID(record_);
-}
-
-- (id)valueForProperty:(ABPropertyID)property {
- id value = GTMCFAutorelease(ABRecordCopyValue(record_, property));
- if (value) {
- if ([[self class] typeOfProperty:property] & kABMultiValueMask) {
- value = [[[GTMABMultiValue alloc] initWithMultiValue:value] autorelease];
- }
- }
- return value;
-}
-
-- (BOOL)setValue:(id)value forProperty:(ABPropertyID)property {
- if (!value) return NO;
- // We check the type here because of
- // Radar 6201046 ABRecordSetValue returns true even if you pass in a bad type
- // for a value
- TypeClassNameMap fullTypeMap[] = {
- { kABStringPropertyType, [NSString class] },
- { kABIntegerPropertyType, [NSNumber class] },
- { kABRealPropertyType, [NSNumber class] },
- { kABDateTimePropertyType, [NSDate class] },
- { kABDictionaryPropertyType, [NSDictionary class] },
- { kABMultiStringPropertyType, [GTMABMultiValue class] },
- { kABMultiRealPropertyType, [GTMABMultiValue class] },
- { kABMultiDateTimePropertyType, [GTMABMultiValue class] },
- { kABMultiDictionaryPropertyType, [GTMABMultiValue class] }
- };
- ABPropertyType type = [[self class] typeOfProperty:property];
- BOOL wasFound = NO;
- for (size_t i = 0; i < sizeof(fullTypeMap) / sizeof(TypeClassNameMap); ++i) {
- if (fullTypeMap[i].pType == type) {
- wasFound = YES;
- if (![[value class] isSubclassOfClass:fullTypeMap[i].class]) {
- return NO;
- }
- }
- }
- if (!wasFound) {
- return NO;
- }
- if (type & kABMultiValueMask) {
- value = (id)[value multiValueRef];
- }
- CFErrorRef cfError = nil;
- bool wasGood = ABRecordSetValue(record_, property, (CFTypeRef)value, &cfError);
- if (cfError) {
- // COV_NF_START
- _GTMDevLog(@"Error in [%@ %@]: %@",
- [self class], NSStringFromSelector(_cmd), cfError);
- CFRelease(cfError);
- // COV_NF_END
- }
- return wasGood ? YES : NO;
-}
-
-- (BOOL)removeValueForProperty:(ABPropertyID)property {
- CFErrorRef cfError = nil;
- // We check to see if the value is in the property because of:
- // Radar 6201005 ABRecordRemoveValue returns true for value that aren't
- // in the record
- id value = [self valueForProperty:property];
- bool wasGood = value && ABRecordRemoveValue(record_, property, &cfError);
- if (cfError) {
- // COV_NF_START
- _GTMDevLog(@"Error in [%@ %@]: %@",
- [self class], NSStringFromSelector(_cmd), cfError);
- CFRelease(cfError);
- // COV_NF_END
- }
- return wasGood ? YES : NO;
-}
-
-- (NSString *)compositeName {
- return GTMCFAutorelease(ABRecordCopyCompositeName(record_));
-}
-
-// COV_NF_START
-// Both of these methods are to be overridden by their subclasses
-+ (ABPropertyType)typeOfProperty:(ABPropertyID)property {
- [self doesNotRecognizeSelector:_cmd];
- return kABInvalidPropertyType;
-}
-
-+ (NSString *)localizedPropertyName:(ABPropertyID)property {
- [self doesNotRecognizeSelector:_cmd];
- return nil;
-}
-// COV_NF_END
-@end
-
-@implementation GTMABPerson
-
-+ (GTMABPerson *)personWithFirstName:(NSString *)first
- lastName:(NSString *)last {
- GTMABPerson *person = [[[self alloc] init] autorelease];
- if (person) {
- BOOL isGood = YES;
- if (first) {
- isGood = [person setValue:first forProperty:kABPersonFirstNameProperty];
- }
- if (isGood && last) {
- isGood = [person setValue:last forProperty:kABPersonLastNameProperty];
- }
- if (!isGood) {
- // COV_NF_START
- // Marked as NF because I don't know how to force an error
- person = nil;
- // COV_NF_END
- }
- }
- return person;
-}
-
-- (id)init {
- ABRecordRef person = ABPersonCreate();
- self = [super initWithRecord:person];
- if (person) {
- CFRelease(person);
- }
- return self;
-}
-
-- (BOOL)setImageData:(NSData *)data {
- CFErrorRef cfError = NULL;
- bool wasGood = NO;
- if (!data) {
- wasGood = ABPersonRemoveImageData([self recordRef], &cfError);
- } else {
- // We verify that the data is good because of:
- // Radar 6202868 ABPersonSetImageData should validate image data
- UIImage *image = [UIImage imageWithData:data];
- wasGood = image && ABPersonSetImageData([self recordRef],
- (CFDataRef)data, &cfError);
- }
- if (cfError) {
- // COV_NF_START
- _GTMDevLog(@"Error in [%@ %@]: %@",
- [self class], NSStringFromSelector(_cmd), cfError);
- CFRelease(cfError);
- // COV_NF_END
- }
- return wasGood ? YES : NO;
-}
-
-- (UIImage *)image {
- return [UIImage imageWithData:[self imageData]];
-}
-
-- (BOOL)setImage:(UIImage *)image {
- NSData *data = UIImagePNGRepresentation(image);
- return [self setImageData:data];
-}
-
-- (NSData *)imageData {
- return GTMCFAutorelease(ABPersonCopyImageData([self recordRef]));
-}
-
-- (NSString *)description {
- return [NSString stringWithFormat:@"%@ %@ %@ %d",
- [self class],
- [self valueForProperty:kABPersonFirstNameProperty],
- [self valueForProperty:kABPersonLastNameProperty],
- [self recordID]];
-}
-
-+ (NSString *)localizedPropertyName:(ABPropertyID)property {
- return GTMCFAutorelease(ABPersonCopyLocalizedPropertyName(property));
-}
-
-+ (ABPersonCompositeNameFormat)compositeNameFormat {
- return ABPersonGetCompositeNameFormat();
-}
-
-+ (ABPropertyType)typeOfProperty:(ABPropertyID)property {
- return ABPersonGetTypeOfProperty(property);
-}
-@end
-
-@implementation GTMABGroup
-
-+ (GTMABGroup *)groupNamed:(NSString *)name {
- GTMABGroup *group = [[[self alloc] init] autorelease];
- if (group) {
- if (![group setValue:name forProperty:kABGroupNameProperty]) {
- // COV_NF_START
- // Can't get setValue to fail for me
- group = nil;
- // COV_NF_END
- }
- }
- return group;
-}
-
-- (id)init {
- ABRecordRef group = ABGroupCreate();
- self = [super initWithRecord:group];
- if (group) {
- CFRelease(group);
- }
- return self;
-}
-
-- (NSArray *)members {
- NSArray *people
- = GTMCFAutorelease(ABGroupCopyArrayOfAllMembers([self recordRef]));
- NSMutableArray *gtmPeople = [NSMutableArray arrayWithCapacity:[people count]];
- for (id person in people) {
- [gtmPeople addObject:[GTMABPerson recordWithRecord:(ABRecordRef)person]];
- }
- return gtmPeople;
-}
-
-- (BOOL)addMember:(GTMABPerson *)person {
- CFErrorRef cfError = nil;
- // We check for person because of
- // Radar 6202860 Passing nil person into ABGroupAddMember crashes
- bool wasGood = person && ABGroupAddMember([self recordRef],
- [person recordRef], &cfError);
- if (cfError) {
- // COV_NF_START
- _GTMDevLog(@"Error in [%@ %@]: %@",
- [self class], NSStringFromSelector(_cmd), cfError);
- CFRelease(cfError);
- // COV_NF_END
- }
- return wasGood ? YES : NO;
-}
-
-- (BOOL)removeMember:(GTMABPerson *)person {
- CFErrorRef cfError = nil;
- // We check for person because of
- // Radar 6202860 Passing nil person into ABGroupAddMember crashes
- // (I know this is remove, but it crashes there too)
- bool wasGood = person && ABGroupRemoveMember([self recordRef],
- [person recordRef], &cfError);
- if (cfError) {
- // COV_NF_START
- _GTMDevLog(@"Error in [%@ %@]: %@",
- [self class], NSStringFromSelector(_cmd), cfError);
- CFRelease(cfError);
- // COV_NF_END
- }
- return wasGood ? YES : NO;
-}
-
-+ (ABPropertyType)typeOfProperty:(ABPropertyID)property {
- ABPropertyType type = kABInvalidPropertyType;
- if (property == kABGroupNameProperty) {
- type = kABStringPropertyType;
- }
- return type;
-}
-
-+ (NSString *)localizedPropertyName:(ABPropertyID)property {
- NSString *name = kGTMABUnknownPropertyName;
- if (property == kABGroupNameProperty) {
- name = NSLocalizedStringFromTable(@"Name",
- @"GTMABAddressBook",
- @"name property");
- }
- return name;
-}
-
-- (NSString *)description {
- return [NSString stringWithFormat:@"%@ %@ %d",
- [self class],
- [self valueForProperty:kABGroupNameProperty],
- [self recordID]];
-}
-@end
-
-@implementation GTMABMultiValue
-- (id)init {
- // Call super init and release so we don't leak
- [[super init] autorelease];
- [self doesNotRecognizeSelector:_cmd];
- return nil; // COV_NF_LINE
-}
-
-- (id)initWithMultiValue:(ABMultiValueRef)multiValue {
- if ((self = [super init])) {
- if (!multiValue) {
- [self release];
- self = nil;
- } else {
- multiValue_ = CFRetain(multiValue);
- }
- }
- return self;
-}
-
-- (id)copyWithZone:(NSZone *)zone {
- return [[GTMABMultiValue alloc] initWithMultiValue:multiValue_];
-}
-
-- (id)mutableCopyWithZone:(NSZone *)zone {
- return [[GTMABMutableMultiValue alloc] initWithMultiValue:multiValue_];
-}
-
-- (NSUInteger)hash {
- // I'm implementing hash instead of using CFHash(multiValue_) because
- // 6203854 ABMultiValues hash to their address
- NSUInteger count = [self count];
- NSUInteger hash = 0;
- for (NSUInteger i = 0; i < count; ++i) {
- NSString *label = [self labelAtIndex:i];
- id value = [self valueAtIndex:i];
- hash += [label hash];
- hash += [value hash];
- }
- return hash;
-}
-
-- (BOOL)isEqual:(id)object {
- // I'm implementing isEqual instea of using CFEquals(multiValue,...) because
- // 6203854 ABMultiValues hash to their address
- // and it appears CFEquals just calls through to hash to compare them.
- BOOL isEqual = NO;
- if ([object respondsToSelector:@selector(multiValueRef)]) {
- isEqual = multiValue_ == [object multiValueRef];
- if (!isEqual) {
- NSUInteger count = [self count];
- NSUInteger objCount = [object count];
- isEqual = count == objCount;
- for (NSUInteger i = 0; isEqual && i < count; ++i) {
- NSString *label = [self labelAtIndex:i];
- NSString *objLabel = [object labelAtIndex:i];
- isEqual = [label isEqual:objLabel];
- if (isEqual) {
- id value = [self valueAtIndex:i];
- id objValue = [object valueAtIndex:i];
- isEqual = [value isEqual:objValue];
- }
- }
- }
- }
- return isEqual;
-}
-
-- (void)dealloc {
- if (multiValue_) {
- CFRelease(multiValue_);
- }
- [super dealloc];
-}
-
-- (ABMultiValueRef)multiValueRef {
- return multiValue_;
-}
-
-- (NSUInteger)count {
- return ABMultiValueGetCount(multiValue_);
-}
-
-- (id)valueAtIndex:(NSUInteger)idx {
- id value = nil;
- if (idx < [self count]) {
- value = GTMCFAutorelease(ABMultiValueCopyValueAtIndex(multiValue_, idx));
- ABPropertyType type = [self propertyType];
- if (type == kABIntegerPropertyType
- || type == kABRealPropertyType
- || type == kABDictionaryPropertyType) {
- // This is because of
- // 6208390 Integer and real values don't work in ABMultiValueRefs
- // Apparently they forget to add a ref count on int, real and
- // dictionary values in ABMultiValueCopyValueAtIndex, although they do
- // remember them for all other types.
- // Once they fix this, this will lead to a leak, but I figure the leak
- // is better than the crash. Our unittests will test to make sure that
- // this is the case, and once we find a system that has this fixed, we
- // can conditionalize this code. Look for testRadar6208390 in
- // GTMABAddressBookTest.m
- // Also, search for 6208390 below and fix the fast enumerator to actually
- // be somewhat performant when this is fixed.
- [value retain];
- }
- }
- return value;
-}
-
-- (NSString *)labelAtIndex:(NSUInteger)idx {
- NSString *label = nil;
- if (idx < [self count]) {
- label = GTMCFAutorelease(ABMultiValueCopyLabelAtIndex(multiValue_, idx));
- }
- return label;
-}
-
-- (ABMultiValueIdentifier)identifierAtIndex:(NSUInteger)idx {
- ABMultiValueIdentifier identifier = kABMultiValueInvalidIdentifier;
- if (idx < [self count]) {
- identifier = ABMultiValueGetIdentifierAtIndex(multiValue_, idx);
- }
- return identifier;
-}
-
-- (NSUInteger)indexForIdentifier:(ABMultiValueIdentifier)identifier {
- NSUInteger idx = ABMultiValueGetIndexForIdentifier(multiValue_, identifier);
- return idx == (NSUInteger)kCFNotFound ? (NSUInteger)NSNotFound : idx;
-}
-
-- (ABPropertyType)propertyType {
- return ABMultiValueGetPropertyType(multiValue_);
-}
-
-- (id)valueForIdentifier:(ABMultiValueIdentifier)identifier {
- return [self valueAtIndex:[self indexForIdentifier:identifier]];
-}
-
-- (NSString *)labelForIdentifier:(ABMultiValueIdentifier)identifier {
- return [self labelAtIndex:[self indexForIdentifier:identifier]];
-}
-
-- (unsigned long*)mutations {
- // We just need some constant non-zero value here so fast enumeration works.
- // Dereferencing self should give us the isa which will stay constant
- // over the enumeration.
- return (unsigned long*)self;
-}
-
-- (NSEnumerator *)valueEnumerator {
- return [GTMABMultiValueEnumerator valueEnumeratorFor:self];
-}
-
-- (NSEnumerator *)labelEnumerator {
- return [GTMABMultiValueEnumerator labelEnumeratorFor:self];
-}
-
-@end
-
-@implementation GTMABMutableMultiValue
-+ (id)valueWithPropertyType:(ABPropertyType)type {
- return [[[self alloc] initWithPropertyType:type] autorelease];
-}
-
-- (id)initWithPropertyType:(ABPropertyType)type {
- ABMutableMultiValueRef ref = nil;
- if (type != kABInvalidPropertyType) {
- ref = ABMultiValueCreateMutable(type);
- }
- self = [super initWithMultiValue:ref];
- if (ref) {
- CFRelease(ref);
- }
- return self;
-}
-
-- (id)initWithMultiValue:(ABMultiValueRef)multiValue {
- ABMutableMultiValueRef ref = nil;
- if (multiValue) {
- ref = ABMultiValueCreateMutableCopy(multiValue);
- }
- self = [super initWithMultiValue:ref];
- if (ref) {
- CFRelease(ref);
- }
- return self;
-}
-
-- (id)initWithMutableMultiValue:(ABMutableMultiValueRef)multiValue {
- return [super initWithMultiValue:multiValue];
-}
-
-- (BOOL)checkValueType:(id)value {
- BOOL isGood = NO;
- if (value) {
- TypeClassNameMap singleValueTypeMap[] = {
- { kABStringPropertyType, [NSString class] },
- { kABIntegerPropertyType, [NSNumber class] },
- { kABRealPropertyType, [NSNumber class] },
- { kABDateTimePropertyType, [NSDate class] },
- { kABDictionaryPropertyType, [NSDictionary class] },
- };
- ABPropertyType type = [self propertyType];
- for (size_t i = 0;
- i < sizeof(singleValueTypeMap) / sizeof(TypeClassNameMap); ++i) {
- if (singleValueTypeMap[i].pType == type) {
- if ([[value class] isSubclassOfClass:singleValueTypeMap[i].class]) {
- isGood = YES;
- break;
- }
- }
- }
- }
- return isGood;
-}
-
-- (ABMultiValueIdentifier)addValue:(id)value withLabel:(CFStringRef)label {
- ABMultiValueIdentifier identifier = kABMultiValueInvalidIdentifier;
- // We check label and value here because of
- // radar 6202827 Passing nil info ABMultiValueAddValueAndLabel causes crash
- if (!label
- || ![self checkValueType:value]
- || !ABMultiValueAddValueAndLabel(multiValue_,
- value,
- label,
- &identifier)) {
- identifier = kABMultiValueInvalidIdentifier;
- } else {
- mutations_++;
- }
- return identifier;
-}
-
-- (ABMultiValueIdentifier)insertValue:(id)value
- withLabel:(CFStringRef)label
- atIndex:(NSUInteger)idx {
- ABMultiValueIdentifier identifier = kABMultiValueInvalidIdentifier;
- // We perform a check here to ensure that we don't get bitten by
- // Radar 6202807 ABMultiValueInsertValueAndLabelAtIndex allows you to insert
- // values past end
- NSUInteger count = [self count];
- // We check label and value here because of
- // radar 6202827 Passing nil info ABMultiValueAddValueAndLabel causes crash
- if (idx > count
- || !label
- || ![self checkValueType:value]
- || !ABMultiValueInsertValueAndLabelAtIndex(multiValue_,
- value,
- label,
- idx,
- &identifier)) {
- identifier = kABMultiValueInvalidIdentifier;
- } else {
- mutations_++;
- }
- return identifier;
-}
-
-- (BOOL)removeValueAndLabelAtIndex:(NSUInteger)idx {
- BOOL isGood = NO;
- NSUInteger count = [self count];
- if (idx < count) {
- if (ABMultiValueRemoveValueAndLabelAtIndex(multiValue_,
- idx)) {
- mutations_++;
- isGood = YES;
- }
- }
- return isGood;
-}
-
-- (BOOL)replaceValueAtIndex:(NSUInteger)idx withValue:(id)value {
- BOOL isGood = NO;
- NSUInteger count = [self count];
- if (idx < count && [self checkValueType:value]) {
- if (ABMultiValueReplaceValueAtIndex(multiValue_,
- value, idx)) {
- mutations_++;
- isGood = YES;
- }
- }
- return isGood;
-}
-
-- (BOOL)replaceLabelAtIndex:(NSUInteger)idx withLabel:(CFStringRef)label{
- BOOL isGood = NO;
- NSUInteger count = [self count];
- if (idx < count) {
- if (ABMultiValueReplaceLabelAtIndex(multiValue_,
- label,
- idx)) {
- mutations_++;
- isGood = YES;
- }
- }
- return isGood;
-}
-
-- (unsigned long*)mutations {
- return &mutations_;
-}
-@end
-
-
-@implementation GTMABMultiValueEnumerator
-
-+ (id)valueEnumeratorFor:(GTMABMultiValue*)enumeree {
- return [[[self alloc] initWithEnumeree:enumeree useLabels:NO] autorelease];
-}
-
-+ (id)labelEnumeratorFor:(GTMABMultiValue*)enumeree {
- return [[[self alloc] initWithEnumeree:enumeree useLabels:YES] autorelease];
-}
-
-- (id)initWithEnumeree:(GTMABMultiValue*)enumeree useLabels:(BOOL)useLabels {
- if ((self = [super init])) {
- if (enumeree) {
- enumeree_ = [enumeree retain];
- useLabels_ = useLabels;
- } else {
- // COV_NF_START
- // Since this is a private class where the enumeree creates us
- // there is no way we should ever get here.
- [self release];
- self = nil;
- // COV_NF_END
- }
- }
- return self;
-}
-
-- (void)dealloc {
- [enumeree_ release];
- [super dealloc];
-}
-
-- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
- objects:(id *)stackbuf
- count:(NSUInteger)len {
- NSUInteger i;
- if (!ref_) {
- count_ = [enumeree_ count];
- ref_ = [enumeree_ multiValueRef];
- }
-
- for (i = 0; state->state < count_ && i < len; ++i, ++state->state) {
- if (useLabels_) {
- stackbuf[i] = GTMCFAutorelease(ABMultiValueCopyLabelAtIndex(ref_,
- state->state));
- } else {
- // Yes this is slow, but necessary in light of radar 6208390
- // Once this is fixed we can go to something similar to the label
- // case which should speed stuff up again. Hopefully anybody who wants
- // real performance is willing to move down to the C API anyways.
- stackbuf[i] = [enumeree_ valueAtIndex:state->state];
- }
- }
-
- state->itemsPtr = stackbuf;
- state->mutationsPtr = [enumeree_ mutations];
- return i;
-}
-
-- (id)nextObject {
- id value = nil;
- if (!ref_) {
- count_ = [enumeree_ count];
- mutations_ = *[enumeree_ mutations];
- ref_ = [enumeree_ multiValueRef];
-
- }
- if (mutations_ != *[enumeree_ mutations]) {
- NSString *reason = [NSString stringWithFormat:@"*** Collection <%@> was "
- "mutated while being enumerated", enumeree_];
- [[NSException exceptionWithName:NSGenericException
- reason:reason
- userInfo:nil] raise];
- }
- if (index_ < count_) {
- if (useLabels_) {
- value = GTMCFAutorelease(ABMultiValueCopyLabelAtIndex(ref_,
- index_));
- } else {
- // Yes this is slow, but necessary in light of radar 6208390
- // Once this is fixed we can go to something similar to the label
- // case which should speed stuff up again. Hopefully anybody who wants
- // real performance is willing to move down to the C API anyways.
- value = [enumeree_ valueAtIndex:index_];
- }
- index_ += 1;
- }
- return value;
-}
-@end
-
diff --git a/iPhone/GTMABAddressBook.strings b/iPhone/GTMABAddressBook.strings
deleted file mode 100644
index b5e010e..0000000
--- a/iPhone/GTMABAddressBook.strings
+++ /dev/null
Binary files differ
diff --git a/iPhone/GTMABAddressBookTest.m b/iPhone/GTMABAddressBookTest.m
deleted file mode 100644
index 17a3096..0000000
--- a/iPhone/GTMABAddressBookTest.m
+++ /dev/null
@@ -1,608 +0,0 @@
-//
-// GTMAddressBookTest.m
-//
-// 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.
-//
-
-#import "GTMSenTestCase.h"
-#import "GTMABAddressBook.h"
-
-@interface GTMABAddressBookTest : GTMTestCase {
- @private
- GTMABAddressBook *book_;
-}
-@end
-
-
-@implementation GTMABAddressBookTest
-- (void)setUp {
- // Create a book forcing it out of it's autorelease pool.
- // I force it out of the release pool, so that we will see any errors
- // for it immediately at teardown, and it will be clear which release
- // caused us problems.
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- book_ = [[GTMABAddressBook addressBook] retain];
- [pool release];
- STAssertNotNil(book_, nil);
- STAssertFalse([book_ hasUnsavedChanges], nil);
-}
-
-- (void)tearDown {
- [book_ release];
-}
-
-- (void)testGenericAddressBook {
- STAssertEqualObjects([GTMABAddressBook localizedLabel:kABHomeLabel],
- @"home",
- nil);
- STAssertThrows([GTMABRecord recordWithRecord:nil], nil);
-}
-
-- (void)testAddingAndRemovingPerson {
- // Create a person
- GTMABPerson *person = [GTMABPerson personWithFirstName:@"Bart"
- lastName:@"Simpson"];
- STAssertNotNil(person, nil);
-
- // Add person
- NSArray *people = [book_ people];
- STAssertFalse([people containsObject:person], nil);
- STAssertTrue([book_ addRecord:person], nil);
-
- // Normally this next line would be STAssertTrue, however due to
- // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work
- // We will check to make sure it stays broken ;-)
- STAssertFalse([book_ hasUnsavedChanges], nil);
-
- people = [book_ people];
- STAssertNotNil(people, nil);
- // Normally this next line would be STAssertTrue, however due to
- // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the people
- // array until it's saved
- // We will check to make sure it stays broken ;-)
- STAssertFalse([people containsObject:person], nil);
-
- // Save book_
- STAssertTrue([book_ save], nil);
- people = [book_ people];
- STAssertNotNil(people, nil);
- STAssertTrue([people containsObject:person], nil);
-
- ABRecordID recordID = [person recordID];
- STAssertNotEquals(recordID, kABRecordInvalidID, nil);
-
- GTMABRecord *record = [book_ personForId:recordID];
- STAssertEqualObjects(record, person, nil);
-
- // Remove person
- STAssertTrue([book_ removeRecord:person], nil);
- // Normally this next line would be STAssertTrue, however due to
- // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work
- // We will check to make sure it stays broken ;-)
- STAssertFalse([book_ hasUnsavedChanges], nil);
-
- // Normally this next line would be STAssertFalse, however due to
- // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the people
- // array until it's saved
- // We will check to make sure it stays broken ;-)
- STAssertTrue([people containsObject:person], nil);
-
- // Save Book
- STAssertTrue([book_ save], nil);
- people = [book_ people];
- STAssertFalse([book_ hasUnsavedChanges], nil);
- STAssertFalse([people containsObject:person], nil);
- record = [book_ personForId:recordID];
- STAssertNil(record, nil);
-
- // Revert book_
- STAssertTrue([book_ addRecord:person], nil);
- // Normally this next line would be STAssertTrue, however due to
- // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work
- // We will check to make sure it stays broken ;-)
- STAssertFalse([book_ hasUnsavedChanges], nil);
-
- [book_ revert];
- STAssertFalse([book_ hasUnsavedChanges], nil);
-
- // Bogus data
- STAssertFalse([book_ addRecord:nil], nil);
- STAssertFalse([book_ removeRecord:nil], nil);
-
- STAssertNotNULL([book_ addressBookRef], nil);
-
-}
-
-- (void)testAddingAndRemovingGroup {
- // Create a group
- GTMABGroup *group = [GTMABGroup groupNamed:@"Test"];
- STAssertNotNil(group, nil);
-
- // Add group
- NSArray *groups = [book_ groups];
- STAssertFalse([groups containsObject:group], nil);
- STAssertTrue([book_ addRecord:group], nil);
-
- // Normally this next line would be STAssertTrue, however due to
- // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work
- // We will check to make sure it stays broken ;-)
- STAssertFalse([book_ hasUnsavedChanges], nil);
-
- groups = [book_ groups];
- STAssertNotNil(groups, nil);
- // Normally this next line would be STAssertTrue, however due to
- // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the groups
- // array until it's saved
- // We will check to make sure it stays broken ;-)
- STAssertFalse([groups containsObject:group], nil);
-
- // Save book_
- STAssertTrue([book_ save], nil);
- groups = [book_ groups];
- STAssertNotNil(groups, nil);
- STAssertTrue([groups containsObject:group], nil);
-
- ABRecordID recordID = [group recordID];
- STAssertNotEquals(recordID, kABRecordInvalidID, nil);
-
- GTMABRecord *record = [book_ groupForId:recordID];
- STAssertEqualObjects(record, group, nil);
-
- // Remove group
- STAssertTrue([book_ removeRecord:group], nil);
- // Normally this next line would be STAssertTrue, however due to
- // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work
- // We will check to make sure it stays broken ;-)
- STAssertFalse([book_ hasUnsavedChanges], nil);
-
- // Normally this next line would be STAssertFalse, however due to
- // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the groups
- // array until it's saved
- // We will check to make sure it stays broken ;-)
- STAssertTrue([groups containsObject:group], nil);
-
- // Save Book
- STAssertTrue([book_ save], nil);
- groups = [book_ groups];
- STAssertFalse([book_ hasUnsavedChanges], nil);
- STAssertFalse([groups containsObject:group], nil);
- record = [book_ groupForId:recordID];
- STAssertNil(record, nil);
-
- // Revert book_
- STAssertTrue([book_ addRecord:group], nil);
- // Normally this next line would be STAssertTrue, however due to
- // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work
- // We will check to make sure it stays broken ;-)
- STAssertFalse([book_ hasUnsavedChanges], nil);
-
- [book_ revert];
- STAssertFalse([book_ hasUnsavedChanges], nil);
-}
-
-- (void)testPerson {
- GTMABPerson *person = [[[GTMABPerson alloc] initWithRecord:nil] autorelease];
- STAssertNil(person, nil);
- person = [GTMABPerson personWithFirstName:@"Bart"
- lastName:nil];
- STAssertNotNil(person, nil);
- STAssertEqualObjects([person compositeName], @"Bart", nil);
- NSString *firstName = [person valueForProperty:kABPersonFirstNameProperty];
- STAssertEqualObjects(firstName, @"Bart", nil);
- NSString *lastName = [person valueForProperty:kABPersonLastNameProperty];
- STAssertNil(lastName, nil);
- STAssertTrue([person removeValueForProperty:kABPersonFirstNameProperty], nil);
- STAssertFalse([person removeValueForProperty:kABPersonFirstNameProperty], nil);
- STAssertFalse([person removeValueForProperty:kABPersonLastNameProperty], nil);
- STAssertFalse([person setValue:nil forProperty:kABPersonFirstNameProperty], nil);
- STAssertFalse([person setValue:[NSNumber numberWithInt:1]
- forProperty:kABPersonFirstNameProperty], nil);
- STAssertFalse([person setValue:@"Bart"
- forProperty:kABPersonBirthdayProperty], nil);
-
- ABPropertyType property
- = [GTMABPerson typeOfProperty:kABPersonLastNameProperty];
- STAssertEquals(property, (ABPropertyType)kABStringPropertyType, nil);
-
- NSString *string
- = [GTMABPerson localizedPropertyName:kABPersonLastNameProperty];
- STAssertEqualObjects(string, @"Last", nil);
-
- string = [GTMABPerson localizedPropertyName:kABRecordInvalidID];
- STAssertEqualObjects(string, kGTMABUnknownPropertyName, nil);
-
- string = [person description];
- STAssertNotNil(string, nil);
-
- ABPersonCompositeNameFormat format = [GTMABPerson compositeNameFormat];
- STAssertTrue(format == kABPersonCompositeNameFormatFirstNameFirst ||
- format == kABPersonCompositeNameFormatLastNameFirst, nil);
-
- NSData *data = [person imageData];
- STAssertNil(data, nil);
- STAssertTrue([person setImageData:nil], nil);
- data = [person imageData];
- STAssertNil(data, nil);
- UIImage *image = [UIImage imageNamed:@"phone.png"];
- STAssertNotNil(image, nil);
- data = UIImagePNGRepresentation(image);
- STAssertTrue([person setImageData:data], nil);
- NSData *data2 = [person imageData];
- STAssertEqualObjects(data, data2, nil);
- STAssertTrue([person setImageData:nil], nil);
- data = [person imageData];
- STAssertNil(data, nil);
-
- STAssertTrue([person setImage:image], nil);
- UIImage *image2 = [person image];
- STAssertNotNil(image2, nil);
- STAssertEqualObjects(UIImagePNGRepresentation(image),
- UIImagePNGRepresentation(image2), nil);
-
- person = [GTMABPerson personWithFirstName:@"Bart"
- lastName:@"Simpson"];
-
- data = [NSData dataWithBytes:"a" length:1];
- STAssertFalse([person setImageData:data], nil);
-
- GTMABMutableMultiValue *value
- = [GTMABMutableMultiValue valueWithPropertyType:kABStringPropertyType];
- STAssertNotNil(value, nil);
- STAssertNotEquals([value addValue:@"222-222-2222"
- withLabel:kABHomeLabel],
- kABMultiValueInvalidIdentifier, nil);
- STAssertNotEquals([value addValue:@"333-333-3333"
- withLabel:kABWorkLabel],
- kABMultiValueInvalidIdentifier, nil);
- STAssertTrue([person setValue:value forProperty:kABPersonPhoneProperty], nil);
- id value2 = [person valueForProperty:kABPersonPhoneProperty];
- STAssertNotNil(value2, nil);
- STAssertEqualObjects(value, value2, nil);
- STAssertEquals([value hash], [value2 hash], nil);
- STAssertNotEquals([person hash], (NSUInteger)0, nil);
-}
-
-- (void)testGroup {
- GTMABGroup *group = [[[GTMABGroup alloc] initWithRecord:nil] autorelease];
- STAssertNil(group, nil);
- group = [GTMABGroup groupNamed:@"TestGroup"];
- STAssertNotNil(group, nil);
- STAssertEqualObjects([group compositeName], @"TestGroup", nil);
- NSString *name = [group valueForProperty:kABGroupNameProperty];
- STAssertEqualObjects(name, @"TestGroup", nil);
- NSString *lastName = [group valueForProperty:kABPersonLastNameProperty];
- STAssertNil(lastName, nil);
- STAssertTrue([group removeValueForProperty:kABGroupNameProperty], nil);
- STAssertFalse([group removeValueForProperty:kABGroupNameProperty], nil);
- STAssertFalse([group removeValueForProperty:kABPersonLastNameProperty], nil);
- STAssertFalse([group setValue:nil forProperty:kABGroupNameProperty], nil);
- STAssertFalse([group setValue:[NSNumber numberWithInt:1]
- forProperty:kABGroupNameProperty], nil);
- STAssertFalse([group setValue:@"Bart"
- forProperty:kABPersonBirthdayProperty], nil);
-
- ABPropertyType property = [GTMABGroup typeOfProperty:kABGroupNameProperty];
- STAssertEquals(property, (ABPropertyType)kABStringPropertyType, nil);
-
- property = [GTMABGroup typeOfProperty:kABPersonLastNameProperty];
- STAssertEquals(property, (ABPropertyType)kABInvalidPropertyType, nil);
-
- NSString *string = [GTMABGroup localizedPropertyName:kABGroupNameProperty];
- STAssertEqualObjects(string, @"Name", nil);
-
- string = [GTMABGroup localizedPropertyName:kABPersonLastNameProperty];
- STAssertEqualObjects(string, kGTMABUnknownPropertyName, nil);
-
- string = [GTMABGroup localizedPropertyName:kABRecordInvalidID];
- STAssertEqualObjects(string, kGTMABUnknownPropertyName, nil);
-
- string = [group description];
- STAssertNotNil(string, nil);
-
- // Adding and removing members
- group = [GTMABGroup groupNamed:@"TestGroup2"];
- NSArray *members = [group members];
- STAssertEquals([members count], (NSUInteger)0, @"Members: %@", members);
-
- STAssertFalse([group addMember:nil], nil);
-
- members = [group members];
- STAssertEquals([members count], (NSUInteger)0, @"Members: %@", members);
-
- GTMABPerson *person = [GTMABPerson personWithFirstName:@"Bart"
- lastName:@"Simpson"];
- STAssertNotNil(person, nil);
- STAssertTrue([book_ addRecord:person], nil);
- STAssertTrue([book_ save], nil);
- STAssertTrue([group addMember:person], nil);
- STAssertTrue([book_ addRecord:group], nil);
- STAssertTrue([book_ save], nil);
- members = [group members];
- STAssertEquals([members count], (NSUInteger)1, @"Members: %@", members);
- STAssertTrue([group removeMember:person], nil);
- STAssertFalse([group removeMember:person], nil);
- STAssertFalse([group removeMember:nil], nil);
- STAssertTrue([book_ removeRecord:group], nil);
- STAssertTrue([book_ removeRecord:person], nil);
- STAssertTrue([book_ save], nil);
-}
-
-
-- (void)testMultiValues {
- STAssertThrows([[GTMABMultiValue alloc] init], nil);
- STAssertThrows([[GTMABMutableMultiValue alloc] init], nil);
- GTMABMultiValue *value = [[GTMABMultiValue alloc] initWithMultiValue:nil];
- STAssertNil(value, nil);
- GTMABMutableMultiValue *mutValue
- = [GTMABMutableMultiValue valueWithPropertyType:kABInvalidPropertyType];
- STAssertNil(mutValue, nil);
- mutValue
- = [[[GTMABMutableMultiValue alloc]
- initWithMutableMultiValue:nil] autorelease];
- STAssertNil(mutValue, nil);
- mutValue
- = [[[GTMABMutableMultiValue alloc]
- initWithMultiValue:nil] autorelease];
- STAssertNil(mutValue, nil);
- const ABPropertyType types[] = {
- kABStringPropertyType,
- kABIntegerPropertyType,
- kABRealPropertyType,
- kABDateTimePropertyType,
- kABDictionaryPropertyType,
- kABMultiStringPropertyType,
- kABMultiIntegerPropertyType,
- kABMultiRealPropertyType,
- kABMultiDateTimePropertyType,
- kABMultiDictionaryPropertyType
- };
- for (size_t i = 0; i < sizeof(types) / sizeof(ABPropertyType); ++i) {
- mutValue = [GTMABMutableMultiValue valueWithPropertyType:types[i]];
- STAssertNotNil(mutValue, nil);
- // Oddly the Apple APIs allow you to create a mutable multi value with
- // either a property type of kABFooPropertyType or kABMultiFooPropertyType
- // and apparently you get back basically the same thing. However if you
- // ask a type that you created with kABMultiFooPropertyType for it's type
- // it returns just kABFooPropertyType.
- STAssertEquals([mutValue propertyType],
- types[i] & ~kABMultiValueMask, nil);
- }
- mutValue = [GTMABMutableMultiValue valueWithPropertyType:kABStringPropertyType];
- STAssertNotNil(mutValue, nil);
- value = [[mutValue copy] autorelease];
- STAssertEqualObjects([value class], [GTMABMultiValue class], nil);
- mutValue = [[value mutableCopy] autorelease];
- STAssertEqualObjects([mutValue class], [GTMABMutableMultiValue class], nil);
- STAssertEquals([mutValue count], (NSUInteger)0, nil);
- STAssertNil([mutValue valueAtIndex:0], nil);
- STAssertNil([mutValue labelAtIndex:0], nil);
- STAssertEquals([mutValue identifierAtIndex:0],
- kABMultiValueInvalidIdentifier, nil);
- STAssertEquals([mutValue propertyType],
- (ABPropertyType)kABStringPropertyType, nil);
- ABMultiValueIdentifier ident = [mutValue addValue:nil
- withLabel:kABHomeLabel];
- STAssertEquals(ident, kABMultiValueInvalidIdentifier, nil);
- ident = [mutValue addValue:@"val1"
- withLabel:nil];
- STAssertEquals(ident, kABMultiValueInvalidIdentifier, nil);
- ident = [mutValue insertValue:@"val1"
- withLabel:nil
- atIndex:0];
- STAssertEquals(ident, kABMultiValueInvalidIdentifier, nil);
- ident = [mutValue insertValue:nil
- withLabel:kABHomeLabel
- atIndex:0];
- STAssertEquals(ident, kABMultiValueInvalidIdentifier, nil);
- ident = [mutValue addValue:@"val1"
- withLabel:kABHomeLabel];
- STAssertNotEquals(ident, kABMultiValueInvalidIdentifier, nil);
- ABMultiValueIdentifier identCheck = [mutValue identifierAtIndex:0];
- STAssertEquals(ident, identCheck, nil);
- NSUInteger idx = [mutValue indexForIdentifier:ident];
- STAssertEquals(idx, (NSUInteger)0, nil);
- STAssertTrue([mutValue replaceLabelAtIndex:0
- withLabel:kABWorkLabel], nil);
- STAssertFalse([mutValue replaceLabelAtIndex:10
- withLabel:kABWorkLabel], nil);
- STAssertTrue([mutValue replaceValueAtIndex:0
- withValue:@"newVal1"], nil);
- STAssertFalse([mutValue replaceValueAtIndex:10
- withValue:@"newVal1"], nil);
-
- STAssertEqualObjects([mutValue valueForIdentifier:ident], @"newVal1", nil);
- STAssertEqualObjects([mutValue labelForIdentifier:ident],
- (NSString *)kABWorkLabel, nil);
-
- ABMultiValueIdentifier ident2 = [mutValue insertValue:@"val2"
- withLabel:kABOtherLabel
- atIndex:0];
- STAssertNotEquals(ident2, kABMultiValueInvalidIdentifier, nil);
- STAssertNotEquals(ident2, ident, nil);
- ABMultiValueIdentifier ident3 = [mutValue insertValue:@"val3"
- withLabel:kABPersonPhoneMainLabel
- atIndex:10];
- STAssertEquals(ident3, kABMultiValueInvalidIdentifier, nil);
- NSUInteger idx3 = [mutValue indexForIdentifier:ident3];
- STAssertEquals(idx3, (NSUInteger)NSNotFound, nil);
- STAssertTrue([mutValue removeValueAndLabelAtIndex:1], nil);
- STAssertFalse([mutValue removeValueAndLabelAtIndex:1], nil);
-
- NSUInteger idx4
- = [mutValue indexForIdentifier:kABMultiValueInvalidIdentifier];
- STAssertEquals(idx4, (NSUInteger)NSNotFound, nil);
-
- STAssertNotNULL([mutValue multiValueRef], nil);
-
- // Enumerator test
- mutValue = [GTMABMutableMultiValue valueWithPropertyType:kABIntegerPropertyType];
- STAssertNotNil(mutValue, nil);
- for (int i = 0; i < 100; i++) {
- NSString *label = [NSString stringWithFormat:@"label %d", i];
- NSNumber *val = [NSNumber numberWithInt:i];
- STAssertNotEquals([mutValue addValue:val
- withLabel:(CFStringRef)label],
- kABMultiValueInvalidIdentifier, nil);
- }
- int count = 0;
- for (NSString *label in [mutValue labelEnumerator]) {
- NSString *testLabel = [NSString stringWithFormat:@"label %d", count++];
- STAssertEqualObjects(label, testLabel, nil);
- }
- count = 0;
- value = [[mutValue copy] autorelease];
- for (NSNumber *val in [value valueEnumerator]) {
- STAssertEqualObjects(val, [NSNumber numberWithInt:count++], nil);
- }
-
- // Test messing with the values while we're enumerating them
- NSEnumerator *labelEnum = [mutValue labelEnumerator];
- NSEnumerator *valueEnum = [mutValue valueEnumerator];
- STAssertNotNil(labelEnum, nil);
- STAssertNotNil(valueEnum, nil);
- STAssertNotNil([labelEnum nextObject], nil);
- STAssertNotNil([valueEnum nextObject], nil);
- STAssertTrue([mutValue removeValueAndLabelAtIndex:0], nil);
- STAssertThrows([labelEnum nextObject], nil);
- STAssertThrows([valueEnum nextObject], nil);
-
- // Test messing with the values while we're fast enumerating them
- // Should throw an exception on the second access.
- BOOL exceptionThrown = NO;
- // Start at one because we removed index 0 above.
- count = 1;
- @try {
- for (NSString *label in [mutValue labelEnumerator]) {
- NSString *testLabel = [NSString stringWithFormat:@"label %d", count++];
- STAssertEqualObjects(label, testLabel, nil);
- STAssertTrue([mutValue removeValueAndLabelAtIndex:50], nil);
- }
- } @catch(NSException *e) {
- STAssertEqualObjects([e name], NSGenericException, @"Got %@ instead", e);
- STAssertEquals(count, 2,
- @"Should have caught it on the second access");
- exceptionThrown = YES;
- } // COV_NF_LINE - because we always catch, this brace doesn't get exec'd
- STAssertTrue(exceptionThrown, @"We should have thrown an exception"
- @" because the values under the enumerator were modified");
-
-}
-
-- (void)testRadar6208390 {
- ABPropertyType types[] = {
- kABStringPropertyType,
- kABIntegerPropertyType,
- kABRealPropertyType,
- kABDateTimePropertyType,
- kABDictionaryPropertyType
- };
- for (size_t j = 0; j < sizeof(types) / sizeof(ABPropertyType); ++j) {
- ABPropertyType type = types[j];
- ABMultiValueRef ref = ABMultiValueCreateMutable(type);
- STAssertNotNULL(ref, nil);
- NSString *label = [[NSString alloc] initWithString:@"label"];
- STAssertNotNil(label, nil);
- id val = nil;
- switch (type) {
- case kABDictionaryPropertyType:
- val = [[NSDictionary alloc] initWithObjectsAndKeys:@"1", @"1", nil];
- break;
-
- case kABStringPropertyType:
- val = [[NSString alloc] initWithFormat:@"value %d"];
- break;
-
- case kABIntegerPropertyType:
- case kABRealPropertyType:
- val = [[NSNumber alloc] initWithInt:143];
- break;
-
- case kABDateTimePropertyType:
- val = [[NSDate alloc] init];
- break;
- }
- STAssertNotNil(val,
- @"Testing type %d, %@", type, val);
- NSUInteger firstRetainCount = [val retainCount];
- STAssertNotEquals(firstRetainCount,
- (NSUInteger)0,
- @"Testing type %d, %@", type, val);
-
- ABMultiValueIdentifier identifier;
- STAssertTrue(ABMultiValueAddValueAndLabel(ref,
- val,
- (CFStringRef)label,
- &identifier),
- @"Testing type %d, %@", type, val);
- NSUInteger secondRetainCount = [val retainCount];
- STAssertEquals(firstRetainCount + 1,
- secondRetainCount,
- @"Testing type %d, %@", type, val);
- [label release];
- [val release];
- NSUInteger thirdRetainCount = [val retainCount];
- STAssertEquals(firstRetainCount,
- thirdRetainCount,
- @"Testing type %d, %@", type, val);
-
- id oldVal = val;
- val = (id)ABMultiValueCopyValueAtIndex(ref, 0);
- NSUInteger fourthRetainCount = [val retainCount];
-
- // kABDictionaryPropertyTypes appear to do an actual copy, so the retain
- // count checking trick won't work. We only check the retain count if
- // we didn't get a new version.
- if (val == oldVal) {
- if (type == kABIntegerPropertyType
- || type == kABRealPropertyType) {
- // We are verifying that yes indeed 6208390 is still broken
- STAssertEquals(fourthRetainCount,
- thirdRetainCount,
- @"Testing type %d, %@. If you see this error it may "
- @"be time to update the code to change retain behaviors"
- @"with this os version", type, val);
- } else {
- STAssertEquals(fourthRetainCount,
- thirdRetainCount + 1,
- @"Testing type %d, %@", type, val);
- [val release];
- }
- } else {
- [val release];
- }
- CFRelease(ref);
- }
-}
-
-// Globals used by testRadar6240394.
-static ABPropertyID gGTMTestID;
-static const ABPropertyID *gGTMTestIDPtr;
-
-void __attribute__((constructor))SetUpIDForTestRadar6240394(void) {
- // These must be set up BEFORE ABAddressBookCreate is called.
- gGTMTestID = kABPersonLastNameProperty;
- gGTMTestIDPtr = &kABPersonLastNameProperty;
-}
-
-- (void)testRadar6240394 {
- // As of iPhone SDK 2.1, the property IDs aren't initialized until
- // ABAddressBookCreate is actually called. They will return zero until
- // then. Logged as radar 6240394.
- STAssertEquals(gGTMTestID, 0, @"If this isn't zero, Apple has fixed 6240394");
- (void)ABAddressBookCreate();
- STAssertEquals(*gGTMTestIDPtr, kABPersonLastNameProperty,
- @"If this doesn't work, something else has broken");
-}
-@end