Skip to content

Instantly share code, notes, and snippets.

@tylerhall
Created September 25, 2011 19:21
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tylerhall/1241004 to your computer and use it in GitHub Desktop.
Save tylerhall/1241004 to your computer and use it in GitHub Desktop.
By inspecting the user's address book and finding the most common city, state, and zip code - we can make an educated guess as to the user's location without using CoreLocation.
#import <Foundation/Foundation.h>
#import <AddressBook/AddressBook.h>
@interface SFBestGuess : NSObject {
NSMutableArray *_cities;
NSMutableArray *_states;
NSMutableArray *_zipCodes;
}
@property (nonatomic, retain) NSMutableArray *cities;
@property (nonatomic, retain) NSMutableArray *states;
@property (nonatomic, retain) NSMutableArray *zipCodes;
- (void)guessLocation;
- (void)incrementOrCreateKey:(NSString *)key inDictionary:(NSMutableDictionary *)dict;
- (NSMutableArray *)sortedDescendingArrayFromDictionary:(NSDictionary *)dict;
@end
#import "SFBestGuess.h"
@implementation SFBestGuess
@synthesize cities = _cities;
@synthesize states = _states;
@synthesize zipCodes = _zipCodes;
- (void)dealloc {
[_cities release], _cities = nil;
[_states release], _states = nil;
[_zipCodes release], _zipCodes = nil;
[super dealloc];
}
- (id)init {
self = [super init];
_cities = [[NSMutableArray alloc] init];
_states = [[NSMutableArray alloc] init];
_zipCodes = [[NSMutableArray alloc] init];
[self guessLocation];
return self;
}
- (void)guessLocation {
NSMutableDictionary *cities = [NSMutableDictionary dictionary];
NSMutableDictionary *states = [NSMutableDictionary dictionary];
NSMutableDictionary *zipCodes = [NSMutableDictionary dictionary];
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
for(int i = 0; i < nPeople; i++) {
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
ABMultiValueRef multi = ABRecordCopyValue(ref, kABPersonAddressProperty);
if(multi) {
NSArray *theArray = [(id)ABMultiValueCopyArrayOfAllValues(multi) autorelease];
NSDictionary *theDict = [theArray objectAtIndex:0];
NSString *city = [theDict objectForKey:@"City"];
[self incrementOrCreateKey:city inDictionary:cities];
NSString *state = [theDict objectForKey:@"State"];
[self incrementOrCreateKey:state inDictionary:states];
NSString *zip = [theDict objectForKey:@"ZIP"];
[self incrementOrCreateKey:zip inDictionary:zipCodes];
CFRelease(multi);
}
}
CFRelease(addressBook);
CFRelease(allPeople);
self.cities = [self sortedDescendingArrayFromDictionary:cities];
self.states = [self sortedDescendingArrayFromDictionary:states];
self.zipCodes = [self sortedDescendingArrayFromDictionary:zipCodes];
}
- (void)incrementOrCreateKey:(NSString *)key inDictionary:(NSMutableDictionary *)dict {
if(key) {
if([dict valueForKey:key]) {
[dict setValue:[NSNumber numberWithInt:[[dict valueForKey:key] intValue] + 1] forKey:key];
} else {
[dict setValue:[NSNumber numberWithInt:1] forKey:key];
}
}
}
- (NSMutableArray *)sortedDescendingArrayFromDictionary:(NSDictionary *)dict {
NSMutableArray *sortedArray = [NSMutableArray array];
NSArray *sortedKeys = [dict keysSortedByValueUsingSelector:@selector(compare:)];
NSString *someKey;
NSEnumerator *e = [sortedKeys reverseObjectEnumerator];
while(someKey = [e nextObject]) {
NSDictionary *tmpDict = [NSDictionary dictionaryWithObjectsAndKeys:someKey, @"key", [dict valueForKey:someKey], @"count", nil];
[sortedArray addObject:tmpDict];
}
return sortedArray;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment