├── .gitignore ├── Forward Geocoder ├── BSAddressComponent.h ├── BSAddressComponent.m ├── BSForwardGeocoder.h ├── BSForwardGeocoder.m ├── BSGoogleV3KmlParser.h ├── BSGoogleV3KmlParser.m ├── BSKmlResult.h └── BSKmlResult.m ├── Forward-Geocoding.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── README └── iPad sample ├── Classes ├── CustomPlacemark.h ├── CustomPlacemark.m ├── Forward_GeocodingAppDelegate.h ├── Forward_GeocodingAppDelegate.m ├── Forward_GeocodingViewController.h └── Forward_GeocodingViewController.m ├── Forward_Geocoding-Info.plist ├── Forward_GeocodingViewController.xib ├── Forward_Geocoding_Prefix.pch ├── MainWindow.xib └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | *~.nib 4 | 5 | build/ 6 | 7 | *.pbxuser 8 | *.perspective 9 | *.perspectivev3 10 | *.mode1v3 11 | *.mode2v3 12 | xcuserdata 13 | -------------------------------------------------------------------------------- /Forward Geocoder/BSAddressComponent.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-13. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | #import 11 | 12 | @interface BSAddressComponent : NSObject 13 | 14 | @property (nonatomic, retain) NSString *longName; 15 | @property (nonatomic, retain) NSString *shortName; 16 | @property (nonatomic, retain) NSArray *types; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Forward Geocoder/BSAddressComponent.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-13. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | #import "BSAddressComponent.h" 12 | 13 | 14 | @implementation BSAddressComponent 15 | @synthesize shortName = _shortName; 16 | @synthesize longName = _longName; 17 | @synthesize types = _types; 18 | 19 | 20 | - (id)initWithCoder:(NSCoder*)decoder { 21 | if (self = [super init]) { 22 | self.shortName = [decoder decodeObjectForKey:@"shortName"]; 23 | self.longName = [decoder decodeObjectForKey:@"longName"]; 24 | self.types = [decoder decodeObjectForKey:@"types"]; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | - (void)encodeWithCoder:(NSCoder*)encoder { 31 | 32 | if (self.shortName) { 33 | [encoder encodeObject:self.shortName 34 | forKey:@"shortName"]; 35 | } 36 | if (self.longName) { 37 | [encoder encodeObject:self.longName 38 | forKey:@"longName"]; 39 | } 40 | if (self.types) { 41 | [encoder encodeObject:self.types 42 | forKey:@"types"]; 43 | } 44 | } 45 | 46 | - (void)dealloc 47 | { 48 | [_shortName release]; 49 | [_longName release]; 50 | [_types release]; 51 | [super dealloc]; 52 | } 53 | @end 54 | -------------------------------------------------------------------------------- /Forward Geocoder/BSForwardGeocoder.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-13. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | 12 | #import 13 | #import 14 | #import "BSGoogleV3KmlParser.h" 15 | 16 | // Enum for geocoding status responses 17 | enum { 18 | G_GEO_SUCCESS = 200, 19 | G_GEO_BAD_REQUEST = 400, 20 | G_GEO_SERVER_ERROR = 500, 21 | G_GEO_MISSING_QUERY = 601, 22 | G_GEO_UNKNOWN_ADDRESS = 602, 23 | G_GEO_UNAVAILABLE_ADDRESS = 603, 24 | G_GEO_UNKNOWN_DIRECTIONS = 604, 25 | G_GEO_BAD_KEY = 610, 26 | G_GEO_TOO_MANY_QUERIES = 620, 27 | G_GEO_NETWORK_ERROR = 900 28 | }; 29 | 30 | #if NS_BLOCKS_AVAILABLE 31 | typedef void (^BSForwardGeocoderSuccess) (NSArray* results); 32 | typedef void (^BSForwardGeocoderFailed) (int status, NSString* errorMessage); 33 | #endif 34 | 35 | @class BSForwardGeocoder; 36 | 37 | @protocol BSForwardGeocoderDelegate 38 | @required 39 | - (void)forwardGeocodingDidSucceed:(BSForwardGeocoder *)geocoder withResults:(NSArray *)results; 40 | @optional 41 | - (void)forwardGeocoderConnectionDidFail:(BSForwardGeocoder *)geocoder withErrorMessage:(NSString *)errorMessage; 42 | - (void)forwardGeocodingDidFail:(BSForwardGeocoder *)geocoder withErrorCode:(int)errorCode andErrorMessage:(NSString *)errorMessage; 43 | @end 44 | 45 | @interface BSForwardGeocoderCoordinateBounds : NSObject 46 | - (id)initWithSouthWest:(CLLocationCoordinate2D)southwest northEast:(CLLocationCoordinate2D)northeast; 47 | + (BSForwardGeocoderCoordinateBounds *)boundsWithSouthWest:(CLLocationCoordinate2D)southwest northEast:(CLLocationCoordinate2D)northeast; 48 | @property (nonatomic, assign) CLLocationCoordinate2D southwest; 49 | @property (nonatomic, assign) CLLocationCoordinate2D northeast; 50 | @end 51 | 52 | @interface BSForwardGeocoder : NSObject 53 | - (id)initWithDelegate:(id)aDelegate; 54 | - (void)forwardGeocodeWithQuery:(NSString *)searchQuery regionBiasing:(NSString *)regionBiasing viewportBiasing:(BSForwardGeocoderCoordinateBounds *)viewportBiasing; 55 | 56 | #if NS_BLOCKS_AVAILABLE 57 | - (void)forwardGeocodeWithQuery:(NSString *)searchQuery regionBiasing:(NSString *)regionBiasing viewportBiasing:(BSForwardGeocoderCoordinateBounds *)viewportBiasing success:(BSForwardGeocoderSuccess)success failure:(BSForwardGeocoderFailed)failure; 58 | #endif 59 | 60 | @property (nonatomic, assign) id delegate; 61 | @property (nonatomic, assign) BOOL useHTTP; 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Forward Geocoder/BSForwardGeocoder.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-13. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | #import "BSForwardGeocoder.h" 12 | 13 | @interface BSForwardGeocoder () 14 | @property (nonatomic, retain) NSURLConnection *geocodeConnection; 15 | @property (nonatomic, retain) NSMutableData *geocodeConnectionData; 16 | #if NS_BLOCKS_AVAILABLE 17 | @property (nonatomic, copy) BSForwardGeocoderSuccess successBlock; 18 | @property (nonatomic, copy) BSForwardGeocoderFailed failureBlock; 19 | #endif 20 | @end 21 | 22 | @implementation BSForwardGeocoder 23 | @synthesize geocodeConnection = _geocodeConnection; 24 | @synthesize geocodeConnectionData = _geocodeConnectionData; 25 | @synthesize delegate = _delegate; 26 | @synthesize useHTTP = _useHTTP; 27 | 28 | #if NS_BLOCKS_AVAILABLE 29 | @synthesize successBlock = _successBlock; 30 | @synthesize failureBlock = _failureBlock; 31 | #endif 32 | 33 | - (void)dealloc 34 | { 35 | #if NS_BLOCKS_AVAILABLE 36 | [_successBlock release]; 37 | [_failureBlock release]; 38 | #endif 39 | 40 | [self.geocodeConnection cancel]; 41 | [_geocodeConnection release]; 42 | [_geocodeConnectionData release]; 43 | 44 | [super dealloc]; 45 | } 46 | 47 | - (id)initWithDelegate:(id)aDelegate 48 | { 49 | if ((self = [super init])) { 50 | _delegate = aDelegate; 51 | } 52 | return self; 53 | } 54 | 55 | // Use Core Foundation method to URL-encode strings, since -stringByAddingPercentEscapesUsingEncoding: 56 | // doesn't do a complete job. This code is copied from AFNetworking 57 | - (NSString *)URLEncodedString:(NSString *)string 58 | { 59 | static NSString * const kBSGeocodingLegalCharactersToBeEscaped = @"?!@#$^&%*+=,:;'\"`<>()[]{}/\\|~ "; 60 | 61 | return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, (CFStringRef)kBSGeocodingLegalCharactersToBeEscaped, kCFStringEncodingUTF8) autorelease]; 62 | } 63 | 64 | - (void)forwardGeocodeWithQuery:(NSString *)searchQuery regionBiasing:(NSString *)regionBiasing viewportBiasing:(BSForwardGeocoderCoordinateBounds *)viewportBiasing 65 | { 66 | if (self.geocodeConnection) { 67 | [self.geocodeConnection cancel]; 68 | } 69 | 70 | // Create the url object for our request. It's important to escape the 71 | // search string to support spaces and international characters 72 | NSString *geocodeUrl = [NSString stringWithFormat:@"%@://maps.google.com/maps/api/geocode/xml?address=%@&sensor=false", self.useHTTP ? @"http" : @"https", [self URLEncodedString:searchQuery]]; 73 | 74 | if (regionBiasing && ![regionBiasing isEqualToString:@""]) { 75 | geocodeUrl = [geocodeUrl stringByAppendingFormat:@"®ion=%@", regionBiasing]; 76 | } 77 | 78 | if (viewportBiasing) { 79 | NSString *boundsString = [NSString stringWithFormat:@"%f,%f|%f,%f", viewportBiasing.southwest.latitude, viewportBiasing.southwest.longitude, viewportBiasing.northeast.latitude, viewportBiasing.northeast.longitude]; 80 | 81 | // We need to escape the parameters 82 | geocodeUrl = [geocodeUrl stringByAppendingFormat:@"&bounds=%@", [self URLEncodedString:boundsString]]; 83 | } 84 | 85 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:geocodeUrl] cachePolicy:NSURLCacheStorageAllowed timeoutInterval:10.0]; 86 | self.geocodeConnection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease]; 87 | } 88 | 89 | #if NS_BLOCKS_AVAILABLE 90 | - (void)forwardGeocodeWithQuery:(NSString *)location regionBiasing:(NSString *)regionBiasing viewportBiasing:(BSForwardGeocoderCoordinateBounds *)viewportBiasing success:(BSForwardGeocoderSuccess)success failure:(BSForwardGeocoderFailed)failure 91 | { 92 | self.successBlock = success; 93 | self.failureBlock = failure; 94 | [self forwardGeocodeWithQuery:location regionBiasing:regionBiasing viewportBiasing:viewportBiasing]; 95 | } 96 | #endif 97 | 98 | - (void)parseGeocodeResponseWithData:(NSData *)responseData 99 | { 100 | NSError *parseError = nil; 101 | 102 | // Run the KML parser 103 | BSGoogleV3KmlParser *parser = [[BSGoogleV3KmlParser alloc] init]; 104 | [parser parseXMLData:responseData parseError:&parseError ignoreAddressComponents:NO]; 105 | 106 | BOOL handeledByBlocks = NO; 107 | 108 | #if NS_BLOCKS_AVAILABLE 109 | if (self.successBlock && parser.statusCode == G_GEO_SUCCESS) { 110 | self.successBlock(parser.results); 111 | handeledByBlocks = YES; 112 | } 113 | else if (self.failureBlock) { 114 | self.failureBlock(parser.statusCode, [parseError localizedDescription]); 115 | handeledByBlocks = YES; 116 | } 117 | #endif 118 | 119 | if (!handeledByBlocks && self.delegate) { 120 | if (!parseError && parser.statusCode == G_GEO_SUCCESS) { 121 | [self.delegate forwardGeocodingDidSucceed:self withResults:parser.results]; 122 | } 123 | else if ([self.delegate respondsToSelector:@selector(forwardGeocoderDidFail:withErrorMessage:)]) { 124 | [self.delegate forwardGeocodingDidFail:self withErrorCode:parser.statusCode andErrorMessage:[parseError localizedDescription]]; 125 | } 126 | } 127 | 128 | [parser release]; 129 | } 130 | 131 | - (void)geocoderConnectionFailedWithErrorMessage:(NSString *)errorMessage 132 | { 133 | BOOL handeledByBlocks = NO; 134 | 135 | #if NS_BLOCKS_AVAILABLE 136 | if (self.failureBlock) { 137 | self.failureBlock(G_GEO_NETWORK_ERROR, errorMessage); 138 | handeledByBlocks = YES; 139 | } 140 | else if (self.delegate && [self.delegate respondsToSelector:@selector(forwardGeocoderConnectionDidFail:withErrorMessage:)]) { 141 | [self.delegate forwardGeocoderConnectionDidFail:self withErrorMessage:errorMessage]; 142 | handeledByBlocks = YES; 143 | } 144 | #endif 145 | 146 | if (!handeledByBlocks && self.delegate && [self.delegate respondsToSelector:@selector(forwardGeocoderConnectionDidFail:withErrorMessage:)]) { 147 | [self.delegate forwardGeocoderConnectionDidFail:self withErrorMessage:errorMessage]; 148 | } 149 | 150 | self.geocodeConnectionData = nil; 151 | self.geocodeConnection = nil; 152 | } 153 | 154 | #pragma mark - NSURLConnection delegate methods 155 | 156 | - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response 157 | { 158 | if (response.statusCode != 200) { 159 | [self.geocodeConnection cancel]; 160 | [self geocoderConnectionFailedWithErrorMessage:@"Google returned an invalid status code"]; 161 | } 162 | else { 163 | self.geocodeConnectionData = [NSMutableData data]; 164 | } 165 | } 166 | 167 | - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 168 | { 169 | [self.geocodeConnectionData appendData:data]; 170 | } 171 | 172 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 173 | { 174 | [self geocoderConnectionFailedWithErrorMessage:[error localizedDescription]]; 175 | } 176 | 177 | - (void)connectionDidFinishLoading:(NSURLConnection *)connection 178 | { 179 | self.geocodeConnection = nil; 180 | [self parseGeocodeResponseWithData:self.geocodeConnectionData]; 181 | self.geocodeConnectionData = nil; 182 | } 183 | 184 | @end 185 | 186 | @implementation BSForwardGeocoderCoordinateBounds 187 | @synthesize southwest = _southwest; 188 | @synthesize northeast = _northeast; 189 | 190 | - (id)initWithSouthWest:(CLLocationCoordinate2D)southwest northEast:(CLLocationCoordinate2D)northeast 191 | { 192 | if ((self = [super init])) { 193 | self.southwest = southwest; 194 | self.northeast = northeast; 195 | } 196 | 197 | return self; 198 | } 199 | 200 | + (BSForwardGeocoderCoordinateBounds *)boundsWithSouthWest:(CLLocationCoordinate2D)southwest northEast:(CLLocationCoordinate2D)northeast 201 | { 202 | return [[[self alloc] initWithSouthWest:southwest northEast:northeast] autorelease]; 203 | } 204 | @end 205 | -------------------------------------------------------------------------------- /Forward Geocoder/BSGoogleV3KmlParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-14. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | #import 12 | #import "BSKmlResult.h" 13 | #import "BSAddressComponent.h" 14 | #import "BSForwardGeocoder.h" 15 | 16 | @interface BSGoogleV3KmlParser : NSObject { 17 | NSMutableString *contentsOfCurrentProperty; 18 | int statusCode; 19 | NSMutableArray *results; 20 | NSMutableArray *addressComponents; 21 | NSMutableArray *typesArray; 22 | BSKmlResult *currentResult; 23 | BSAddressComponent *currentAddressComponent; 24 | BOOL ignoreAddressComponents; 25 | BOOL isLocation; 26 | BOOL isViewPort; 27 | BOOL isBounds; 28 | BOOL isSouthWest; 29 | } 30 | 31 | @property (nonatomic, readonly) int statusCode; 32 | @property (nonatomic, readonly) NSMutableArray *results; 33 | 34 | - (BOOL)parseXMLData:(NSData *)URL 35 | parseError:(NSError **)error 36 | ignoreAddressComponents:(BOOL)ignore; 37 | 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Forward Geocoder/BSGoogleV3KmlParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-14. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | /** 12 | 13 | Kml Parser for Googles geocoding service version 3. Find out more @ Google: 14 | http://code.google.com/apis/maps/documentation/geocoding/index.html 15 | 16 | **/ 17 | 18 | #import "BSGoogleV3KmlParser.h" 19 | 20 | 21 | @implementation BSGoogleV3KmlParser 22 | 23 | @synthesize statusCode, results; 24 | 25 | - (BOOL)parseXMLData:(NSData *)data parseError:(NSError **)error ignoreAddressComponents:(BOOL)ignore 26 | { 27 | BOOL successfull = TRUE; 28 | 29 | ignoreAddressComponents = ignore; 30 | 31 | // Load the data trough NSData, NSXMLParser leaks when loading data 32 | NSData *xmlData = [[NSData alloc] initWithData:data]; 33 | 34 | // Create XML parser 35 | NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData]; 36 | 37 | // Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks. 38 | [parser setDelegate:self]; 39 | 40 | [parser setShouldProcessNamespaces:NO]; 41 | [parser setShouldReportNamespacePrefixes:NO]; 42 | [parser setShouldResolveExternalEntities:NO]; 43 | 44 | // Start parsing 45 | [parser parse]; 46 | 47 | NSError *parseError = [parser parserError]; 48 | if (parseError && error) { 49 | *error = parseError; 50 | 51 | successfull = FALSE; 52 | } 53 | 54 | [parser release]; 55 | [xmlData release]; 56 | 57 | return successfull; 58 | } 59 | 60 | - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName 61 | namespaceURI:(NSString *)namespaceURI 62 | qualifiedName:(NSString *)qName 63 | attributes:(NSDictionary *)attributeDict 64 | { 65 | if (qName) { 66 | elementName = qName; 67 | } 68 | 69 | // The response could contain multiple placemarks 70 | if([elementName isEqualToString:@"result"]) 71 | { 72 | // Set up an array to hold placemarks 73 | if(results == nil) 74 | { 75 | results = [[NSMutableArray alloc] init]; 76 | } 77 | 78 | // Create a new placemark object to fill with information 79 | currentResult = [[BSKmlResult alloc] init]; 80 | 81 | isLocation = NO; 82 | isViewPort = NO; 83 | isBounds = NO; 84 | isSouthWest = NO; 85 | } 86 | else if(ignoreAddressComponents == FALSE && [elementName isEqualToString:@"address_component"]) 87 | { 88 | // Set up an array to hold address components 89 | if(addressComponents == nil) 90 | { 91 | addressComponents = [[NSMutableArray alloc] init]; 92 | } 93 | 94 | currentAddressComponent = [[BSAddressComponent alloc] init]; 95 | typesArray = [[NSMutableArray alloc] init]; 96 | } 97 | else if([elementName isEqualToString:@"location"]) { 98 | isLocation = YES; 99 | } 100 | else if([elementName isEqualToString:@"viewport"]) { 101 | isViewPort = YES; 102 | } 103 | else if([elementName isEqualToString:@"bounds"]) { 104 | isBounds = YES; 105 | } 106 | else if([elementName isEqualToString:@"southwest"]) { 107 | isSouthWest = YES; 108 | } 109 | 110 | 111 | 112 | // These are the elements we read information from. 113 | if(([elementName isEqualToString:@"status"] || [elementName isEqualToString:@"formatted_address"] || 114 | [elementName isEqualToString:@"lat"] || [elementName isEqualToString:@"lng"]) || 115 | (ignoreAddressComponents == FALSE && ([elementName isEqualToString:@"type"] || 116 | [elementName isEqualToString:@"long_name"] || 117 | [elementName isEqualToString:@"short_name"]) 118 | ) 119 | ) 120 | { 121 | // Create a mutable string to hold the contents of the elements. 122 | // The content is collected in parser:foundCharacters:. 123 | if(contentsOfCurrentProperty == nil) 124 | { 125 | contentsOfCurrentProperty = [NSMutableString string]; 126 | } 127 | else 128 | { 129 | [contentsOfCurrentProperty setString:@""]; 130 | } 131 | } 132 | else if (contentsOfCurrentProperty != nil) 133 | { 134 | // If we're not interested in the element we set the variable used 135 | // to collect information to nil. 136 | contentsOfCurrentProperty = nil; 137 | } 138 | 139 | } 140 | 141 | - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 142 | namespaceURI:(NSString *)namespaceURI 143 | qualifiedName:(NSString *)qName 144 | { 145 | if (qName) { 146 | elementName = qName; 147 | } 148 | 149 | // If we reach the end of a placemark element we add it to our array 150 | if([elementName isEqualToString:@"result"]) 151 | { 152 | if(currentResult != nil) 153 | { 154 | currentResult.addressComponents = addressComponents; 155 | [addressComponents release]; 156 | addressComponents = nil; 157 | 158 | [results addObject:currentResult]; 159 | [currentResult release]; 160 | currentResult = nil; 161 | } 162 | } 163 | else if ([elementName isEqualToString:@"address_component"]) { 164 | if(currentAddressComponent != nil) 165 | { 166 | currentAddressComponent.types = typesArray; 167 | [typesArray release]; 168 | typesArray = nil; 169 | 170 | [addressComponents addObject:currentAddressComponent]; 171 | [currentAddressComponent release]; 172 | currentAddressComponent = nil; 173 | } 174 | } 175 | else if ([elementName isEqualToString:@"location"]) { 176 | isLocation = NO; 177 | } 178 | else if ([elementName isEqualToString:@"viewport"]) { 179 | isViewPort = NO; 180 | } 181 | else if ([elementName isEqualToString:@"southwest"]) { 182 | isSouthWest = NO; 183 | } 184 | 185 | // If contentsOfCurrentProperty is nil we're not interested in the 186 | // collected data 187 | if(contentsOfCurrentProperty == nil) 188 | return; 189 | 190 | NSString* elementValue = [[NSString alloc] initWithString:contentsOfCurrentProperty]; 191 | 192 | if ([elementName isEqualToString:@"status"]) { 193 | if([elementValue isEqualToString:@"OK"]) 194 | { 195 | statusCode = G_GEO_SUCCESS; 196 | } 197 | else if([elementValue isEqualToString:@"ZERO_RESULTS"]) 198 | { 199 | statusCode = G_GEO_UNKNOWN_ADDRESS; 200 | } 201 | else if([elementValue isEqualToString:@"OVER_QUERY_LIMIT"]) 202 | { 203 | statusCode = G_GEO_TOO_MANY_QUERIES; 204 | } 205 | else if([elementValue isEqualToString:@"REQUEST_DENIED"]) 206 | { 207 | statusCode = G_GEO_SERVER_ERROR; 208 | } 209 | else if([elementValue isEqualToString:@"INVALID_REQUEST"]) 210 | { 211 | statusCode = G_GEO_BAD_REQUEST; 212 | } 213 | 214 | } 215 | else if ([elementName isEqualToString:@"long_name"] && currentAddressComponent != nil) { 216 | currentAddressComponent.longName = elementValue; 217 | } 218 | else if ([elementName isEqualToString:@"short_name"] && currentAddressComponent != nil) { 219 | currentAddressComponent.shortName = elementValue; 220 | } 221 | else if ([elementName isEqualToString:@"type"]) { 222 | [typesArray addObject:elementValue]; 223 | } 224 | else if ([elementName isEqualToString:@"formatted_address"]) { 225 | currentResult.address = elementValue; 226 | 227 | } 228 | else if ([elementName isEqualToString:@"lat"]) { 229 | if(isLocation) { 230 | currentResult.latitude = [elementValue floatValue]; 231 | } 232 | else if(isViewPort) 233 | { 234 | if(isSouthWest) { 235 | currentResult.viewportSouthWestLat = [elementValue floatValue]; 236 | } 237 | else { 238 | currentResult.viewportNorthEastLat = [elementValue floatValue]; 239 | } 240 | 241 | } 242 | else if(isBounds) 243 | { 244 | if(isSouthWest) { 245 | currentResult.boundsSouthWestLat = [elementValue floatValue]; 246 | } 247 | else { 248 | currentResult.boundsNorthEastLat = [elementValue floatValue]; 249 | } 250 | } 251 | } 252 | else if ([elementName isEqualToString:@"lng"]) { 253 | if(isLocation) { 254 | currentResult.longitude = [elementValue floatValue]; 255 | } 256 | else if(isViewPort) 257 | { 258 | if(isSouthWest) { 259 | currentResult.viewportSouthWestLon = [elementValue floatValue]; 260 | } 261 | else { 262 | currentResult.viewportNorthEastLon = [elementValue floatValue]; 263 | } 264 | 265 | } 266 | else if(isBounds) 267 | { 268 | if(isSouthWest) { 269 | currentResult.boundsSouthWestLon = [elementValue floatValue]; 270 | } 271 | else { 272 | currentResult.boundsNorthEastLon = [elementValue floatValue]; 273 | } 274 | } 275 | } 276 | 277 | 278 | 279 | [elementValue release]; 280 | contentsOfCurrentProperty = nil; 281 | } 282 | 283 | - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 284 | { 285 | if (contentsOfCurrentProperty) { 286 | // If the current element is one whose content we care about, append 'string' 287 | // to the property that holds the content of the current element. 288 | [contentsOfCurrentProperty appendString:string]; 289 | } 290 | } 291 | 292 | -(void)dealloc 293 | { 294 | [results release]; 295 | [super dealloc]; 296 | } 297 | 298 | 299 | @end 300 | -------------------------------------------------------------------------------- /Forward Geocoder/BSKmlResult.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-13. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | #import 12 | #import 13 | #import "BSAddressComponent.h" 14 | 15 | @interface BSKmlResult : NSObject 16 | 17 | @property (nonatomic, retain) NSString *address; 18 | @property (nonatomic, assign) NSInteger accuracy; 19 | @property (nonatomic, retain) NSString *countryNameCode; 20 | @property (nonatomic, retain) NSString *countryName; 21 | @property (nonatomic, retain) NSString *subAdministrativeAreaName; 22 | @property (nonatomic, retain) NSString *localityName; 23 | @property (nonatomic, retain) NSArray *addressComponents; 24 | @property (nonatomic, assign) float latitude; 25 | @property (nonatomic, assign) float longitude; 26 | @property (nonatomic, assign) float viewportSouthWestLat; 27 | @property (nonatomic, assign) float viewportSouthWestLon; 28 | @property (nonatomic, assign) float viewportNorthEastLat; 29 | @property (nonatomic, assign) float viewportNorthEastLon; 30 | @property (nonatomic, assign) float boundsSouthWestLat; 31 | @property (nonatomic, assign) float boundsSouthWestLon; 32 | @property (nonatomic, assign) float boundsNorthEastLat; 33 | @property (nonatomic, assign) float boundsNorthEastLon; 34 | @property (readonly) CLLocationCoordinate2D coordinate; 35 | @property (readonly) MKCoordinateSpan coordinateSpan; 36 | @property (readonly) MKCoordinateRegion coordinateRegion; 37 | 38 | - (NSArray*)findAddressComponent:(NSString*)typeName; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Forward Geocoder/BSKmlResult.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-13. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | /** 12 | 13 | Object for storing placemark results from Googles geocoding API 14 | 15 | **/ 16 | 17 | #import "BSKmlResult.h" 18 | 19 | 20 | @implementation BSKmlResult 21 | 22 | @synthesize address = _address; 23 | @synthesize accuracy = _accuracy; 24 | @synthesize countryNameCode = _countryNameCode; 25 | @synthesize countryName = _countryName; 26 | @synthesize subAdministrativeAreaName = _subAdministrativeAreaName; 27 | @synthesize localityName = _localityName; 28 | @synthesize addressComponents = _addressComponents; 29 | @synthesize viewportSouthWestLat = _viewportSouthWestLat; 30 | @synthesize viewportSouthWestLon = _viewportSouthWestLon; 31 | @synthesize viewportNorthEastLat = _viewportNorthEastLat; 32 | @synthesize viewportNorthEastLon = _viewportNorthEastLon; 33 | @synthesize boundsSouthWestLat = _boundsSouthWestLat; 34 | @synthesize boundsSouthWestLon = _boundsSouthWestLon; 35 | @synthesize boundsNorthEastLat = _boundsNorthEastLat; 36 | @synthesize boundsNorthEastLon = boundsNorthEastLon; 37 | @synthesize latitude = _latitude; 38 | @synthesize longitude = _longitude; 39 | 40 | 41 | - (id)initWithCoder:(NSCoder*)decoder { 42 | if (self = [super init]) { 43 | self.address = [decoder decodeObjectForKey:@"address"]; 44 | self.countryNameCode = [decoder decodeObjectForKey:@"countryNameCode"]; 45 | self.countryName = [decoder decodeObjectForKey:@"countryName"]; 46 | self.subAdministrativeAreaName = [decoder decodeObjectForKey:@"subAdministrativeAreaName"]; 47 | self.localityName = [decoder decodeObjectForKey:@"localityName"]; 48 | self.addressComponents = [decoder decodeObjectForKey:@"addressComponents"]; 49 | 50 | self.accuracy = [decoder decodeIntegerForKey:@"accuracy"]; 51 | 52 | self.latitude = [decoder decodeFloatForKey:@"latitude"]; 53 | self.longitude = [decoder decodeFloatForKey:@"longitude"]; 54 | self.viewportSouthWestLat = [decoder decodeFloatForKey:@"viewportSouthWestLat"]; 55 | self.viewportSouthWestLon = [decoder decodeFloatForKey:@"viewportSouthWestLon"]; 56 | self.viewportNorthEastLat = [decoder decodeFloatForKey:@"viewportNorthEastLat"]; 57 | self.viewportNorthEastLon = [decoder decodeFloatForKey:@"viewportNorthEastLon"]; 58 | 59 | self.boundsSouthWestLat = [decoder decodeFloatForKey:@"boundsSouthWestLat"]; 60 | self.boundsSouthWestLon = [decoder decodeFloatForKey:@"boundsSouthWestLon"]; 61 | self.boundsNorthEastLat = [decoder decodeFloatForKey:@"boundsNorthEastLat"]; 62 | self.boundsNorthEastLon = [decoder decodeFloatForKey:@"boundsNorthEastLon"]; 63 | 64 | } 65 | 66 | return self; 67 | } 68 | 69 | - (void)encodeWithCoder:(NSCoder*)encoder { 70 | 71 | if (self.address) { 72 | [encoder encodeObject:self.address 73 | forKey:@"address"]; 74 | } 75 | if (self.countryNameCode) { 76 | [encoder encodeObject:self.countryNameCode 77 | forKey:@"countryNameCode"]; 78 | } 79 | if (self.countryName) { 80 | [encoder encodeObject:self.countryName 81 | forKey:@"countryName"]; 82 | } 83 | if (self.subAdministrativeAreaName) { 84 | [encoder encodeObject:self.subAdministrativeAreaName 85 | forKey:@"subAdministrativeAreaName"]; 86 | } 87 | if (self.localityName) { 88 | [encoder encodeObject:self.localityName 89 | forKey:@"localityName"]; 90 | } 91 | if (self.addressComponents) { 92 | [encoder encodeObject:self.addressComponents 93 | forKey:@"addressComponents"]; 94 | } 95 | [encoder encodeInteger:self.accuracy forKey:@"accuracy"]; 96 | [encoder encodeFloat:self.latitude forKey:@"latitude"]; 97 | [encoder encodeFloat:self.longitude forKey:@"longitude"]; 98 | 99 | [encoder encodeFloat:self.viewportSouthWestLat forKey:@"viewportSouthWestLat"]; 100 | [encoder encodeFloat:self.viewportSouthWestLon forKey:@"viewportSouthWestLon"]; 101 | [encoder encodeFloat:self.viewportNorthEastLat forKey:@"viewportNorthEastLat"]; 102 | [encoder encodeFloat:self.viewportNorthEastLon forKey:@"viewportNorthEastLon"]; 103 | 104 | [encoder encodeFloat:self.boundsSouthWestLat forKey:@"boundsSouthWestLat"]; 105 | [encoder encodeFloat:self.boundsSouthWestLon forKey:@"boundsSouthWestLon"]; 106 | [encoder encodeFloat:self.boundsNorthEastLat forKey:@"boundsNorthEastLat"]; 107 | [encoder encodeFloat:self.boundsNorthEastLon forKey:@"boundsNorthEastLon"]; 108 | } 109 | 110 | - (void)dealloc 111 | { 112 | [_address release]; 113 | [_countryNameCode release]; 114 | [_countryName release]; 115 | [_subAdministrativeAreaName release]; 116 | [_localityName release]; 117 | [_addressComponents release]; 118 | [super dealloc]; 119 | } 120 | 121 | - (CLLocationCoordinate2D)coordinate 122 | { 123 | CLLocationCoordinate2D coordinate = {self.latitude, self.longitude}; 124 | return coordinate; 125 | } 126 | 127 | - (MKCoordinateSpan)coordinateSpan 128 | { 129 | // Calculate the difference between north and south to create a span. 130 | float latitudeDelta = fabs(fabs(self.viewportNorthEastLat) - fabs(self.viewportSouthWestLat)); 131 | float longitudeDelta = fabs(fabs(self.viewportNorthEastLon) - fabs(self.viewportSouthWestLon)); 132 | 133 | MKCoordinateSpan spn = {latitudeDelta, longitudeDelta}; 134 | 135 | return spn; 136 | } 137 | 138 | - (MKCoordinateRegion)coordinateRegion 139 | { 140 | MKCoordinateRegion region; 141 | region.center = self.coordinate; 142 | region.span = self.coordinateSpan; 143 | 144 | return region; 145 | } 146 | 147 | - (NSArray*)findAddressComponent:(NSString*)typeName 148 | { 149 | NSMutableArray *matchingComponents = [[NSMutableArray alloc] init]; 150 | 151 | for (int i = 0, components = [self.addressComponents count]; i < components; i++) { 152 | BSAddressComponent *component = [self.addressComponents objectAtIndex:i]; 153 | if (component.types != nil) { 154 | for(int j = 0, typesCount = [component.types count]; j < typesCount; j++) { 155 | NSString * type = [component.types objectAtIndex:j]; 156 | if ([type isEqualToString:typeName]) { 157 | [matchingComponents addObject:component]; 158 | break; 159 | } 160 | } 161 | } 162 | 163 | } 164 | 165 | return [matchingComponents autorelease]; 166 | } 167 | 168 | @end 169 | -------------------------------------------------------------------------------- /Forward-Geocoding.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 11 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 12 | 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; 13 | F4786646149387900060893E /* BSForwardGeocoder.m in Sources */ = {isa = PBXBuildFile; fileRef = F478663E149387900060893E /* BSForwardGeocoder.m */; }; 14 | F4786647149387900060893E /* BSAddressComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = F478663F149387900060893E /* BSAddressComponent.m */; }; 15 | F4786648149387900060893E /* BSKmlResult.m in Sources */ = {isa = PBXBuildFile; fileRef = F4786640149387900060893E /* BSKmlResult.m */; }; 16 | F4786649149387900060893E /* BSGoogleV3KmlParser.m in Sources */ = {isa = PBXBuildFile; fileRef = F4786645149387900060893E /* BSGoogleV3KmlParser.m */; }; 17 | F478664D149387BC0060893E /* CustomPlacemark.m in Sources */ = {isa = PBXBuildFile; fileRef = F478664B149387BC0060893E /* CustomPlacemark.m */; }; 18 | F4786655149387EA0060893E /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = F478664F149387EA0060893E /* MainWindow.xib */; }; 19 | F4786656149387EA0060893E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F4786650149387EA0060893E /* main.m */; }; 20 | F4786658149387EA0060893E /* Forward_GeocodingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4786652149387EA0060893E /* Forward_GeocodingViewController.xib */; }; 21 | F478665F149388290060893E /* Forward_GeocodingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F478665B149388290060893E /* Forward_GeocodingViewController.m */; }; 22 | F4786660149388290060893E /* Forward_GeocodingAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F478665D149388290060893E /* Forward_GeocodingAppDelegate.m */; }; 23 | F4C7A3B6114CFC0F009DC9F7 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4C7A3B5114CFC0F009DC9F7 /* MapKit.framework */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 28 | 1D6058910D05DD3D006BFB54 /* Forward-Geocoding.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Forward-Geocoding.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 30 | 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 31 | F478663E149387900060893E /* BSForwardGeocoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BSForwardGeocoder.m; path = "Forward Geocoder/BSForwardGeocoder.m"; sourceTree = SOURCE_ROOT; }; 32 | F478663F149387900060893E /* BSAddressComponent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BSAddressComponent.m; path = "Forward Geocoder/BSAddressComponent.m"; sourceTree = SOURCE_ROOT; }; 33 | F4786640149387900060893E /* BSKmlResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BSKmlResult.m; path = "Forward Geocoder/BSKmlResult.m"; sourceTree = SOURCE_ROOT; }; 34 | F4786641149387900060893E /* BSKmlResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BSKmlResult.h; path = "Forward Geocoder/BSKmlResult.h"; sourceTree = SOURCE_ROOT; }; 35 | F4786642149387900060893E /* BSAddressComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BSAddressComponent.h; path = "Forward Geocoder/BSAddressComponent.h"; sourceTree = SOURCE_ROOT; }; 36 | F4786643149387900060893E /* BSForwardGeocoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BSForwardGeocoder.h; path = "Forward Geocoder/BSForwardGeocoder.h"; sourceTree = SOURCE_ROOT; }; 37 | F4786644149387900060893E /* BSGoogleV3KmlParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BSGoogleV3KmlParser.h; path = "Forward Geocoder/BSGoogleV3KmlParser.h"; sourceTree = SOURCE_ROOT; }; 38 | F4786645149387900060893E /* BSGoogleV3KmlParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BSGoogleV3KmlParser.m; path = "Forward Geocoder/BSGoogleV3KmlParser.m"; sourceTree = SOURCE_ROOT; }; 39 | F478664B149387BC0060893E /* CustomPlacemark.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CustomPlacemark.m; path = "iPad sample/Classes/CustomPlacemark.m"; sourceTree = SOURCE_ROOT; }; 40 | F478664C149387BC0060893E /* CustomPlacemark.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomPlacemark.h; path = "iPad sample/Classes/CustomPlacemark.h"; sourceTree = SOURCE_ROOT; }; 41 | F478664F149387EA0060893E /* MainWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MainWindow.xib; path = "iPad sample/MainWindow.xib"; sourceTree = ""; }; 42 | F4786650149387EA0060893E /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = "iPad sample/main.m"; sourceTree = ""; }; 43 | F4786652149387EA0060893E /* Forward_GeocodingViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = Forward_GeocodingViewController.xib; path = "iPad sample/Forward_GeocodingViewController.xib"; sourceTree = ""; }; 44 | F4786653149387EA0060893E /* Forward_Geocoding-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Forward_Geocoding-Info.plist"; path = "iPad sample/Forward_Geocoding-Info.plist"; sourceTree = ""; }; 45 | F4786654149387EA0060893E /* Forward_Geocoding_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Forward_Geocoding_Prefix.pch; path = "iPad sample/Forward_Geocoding_Prefix.pch"; sourceTree = ""; }; 46 | F478665B149388290060893E /* Forward_GeocodingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Forward_GeocodingViewController.m; path = "iPad sample/Classes/Forward_GeocodingViewController.m"; sourceTree = SOURCE_ROOT; }; 47 | F478665C149388290060893E /* Forward_GeocodingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Forward_GeocodingViewController.h; path = "iPad sample/Classes/Forward_GeocodingViewController.h"; sourceTree = SOURCE_ROOT; }; 48 | F478665D149388290060893E /* Forward_GeocodingAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Forward_GeocodingAppDelegate.m; path = "iPad sample/Classes/Forward_GeocodingAppDelegate.m"; sourceTree = SOURCE_ROOT; }; 49 | F478665E149388290060893E /* Forward_GeocodingAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Forward_GeocodingAppDelegate.h; path = "iPad sample/Classes/Forward_GeocodingAppDelegate.h"; sourceTree = SOURCE_ROOT; }; 50 | F4C7A3B5114CFC0F009DC9F7 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 59 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 60 | 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, 61 | F4C7A3B6114CFC0F009DC9F7 /* MapKit.framework in Frameworks */, 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | /* End PBXFrameworksBuildPhase section */ 66 | 67 | /* Begin PBXGroup section */ 68 | 080E96DDFE201D6D7F000001 /* Classes */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | F4C7A417114D02B7009DC9F7 /* Placemark */, 72 | F478665C149388290060893E /* Forward_GeocodingViewController.h */, 73 | F478665B149388290060893E /* Forward_GeocodingViewController.m */, 74 | F478665D149388290060893E /* Forward_GeocodingAppDelegate.m */, 75 | F478665E149388290060893E /* Forward_GeocodingAppDelegate.h */, 76 | ); 77 | path = Classes; 78 | sourceTree = ""; 79 | }; 80 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 1D6058910D05DD3D006BFB54 /* Forward-Geocoding.app */, 84 | ); 85 | name = Products; 86 | sourceTree = ""; 87 | }; 88 | 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | F4C7A371114CF445009DC9F7 /* Forward Geocoding */, 92 | F478664E149387D10060893E /* iPad sample */, 93 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 94 | 19C28FACFE9D520D11CA2CBB /* Products */, 95 | ); 96 | comments = "//\n// Created by Björn Sållarp on 2010-03-13.\n// NO Copyright 2010 MightyLittle Industries. NO rights reserved.\n// \n// Use this code any way you like. If you do like it, please\n// link to my blog and/or write a friendly comment. Thank you!\n//\n// Read my blog @ http://blog.sallarp.com\n//"; 97 | name = CustomTemplate; 98 | sourceTree = ""; 99 | }; 100 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | F4786654149387EA0060893E /* Forward_Geocoding_Prefix.pch */, 104 | F4786650149387EA0060893E /* main.m */, 105 | F4786653149387EA0060893E /* Forward_Geocoding-Info.plist */, 106 | ); 107 | name = "Other Sources"; 108 | sourceTree = ""; 109 | }; 110 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 114 | 1D30AB110D05D00D00671497 /* Foundation.framework */, 115 | 288765A40DF7441C002DB57D /* CoreGraphics.framework */, 116 | F4C7A3B5114CFC0F009DC9F7 /* MapKit.framework */, 117 | ); 118 | name = Frameworks; 119 | sourceTree = ""; 120 | }; 121 | F478664E149387D10060893E /* iPad sample */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 080E96DDFE201D6D7F000001 /* Classes */, 125 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 126 | F478665A149388020060893E /* Resources */, 127 | ); 128 | name = "iPad sample"; 129 | sourceTree = ""; 130 | }; 131 | F478665A149388020060893E /* Resources */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | F478664F149387EA0060893E /* MainWindow.xib */, 135 | F4786652149387EA0060893E /* Forward_GeocodingViewController.xib */, 136 | ); 137 | name = Resources; 138 | sourceTree = ""; 139 | }; 140 | F4C7A371114CF445009DC9F7 /* Forward Geocoding */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | F4786642149387900060893E /* BSAddressComponent.h */, 144 | F478663F149387900060893E /* BSAddressComponent.m */, 145 | F4786640149387900060893E /* BSKmlResult.m */, 146 | F4786641149387900060893E /* BSKmlResult.h */, 147 | F4786643149387900060893E /* BSForwardGeocoder.h */, 148 | F478663E149387900060893E /* BSForwardGeocoder.m */, 149 | F4786644149387900060893E /* BSGoogleV3KmlParser.h */, 150 | F4786645149387900060893E /* BSGoogleV3KmlParser.m */, 151 | ); 152 | name = "Forward Geocoding"; 153 | path = Classes; 154 | sourceTree = ""; 155 | }; 156 | F4C7A417114D02B7009DC9F7 /* Placemark */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | F478664C149387BC0060893E /* CustomPlacemark.h */, 160 | F478664B149387BC0060893E /* CustomPlacemark.m */, 161 | ); 162 | name = Placemark; 163 | sourceTree = ""; 164 | }; 165 | /* End PBXGroup section */ 166 | 167 | /* Begin PBXNativeTarget section */ 168 | 1D6058900D05DD3D006BFB54 /* Forward-Geocoding */ = { 169 | isa = PBXNativeTarget; 170 | buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "Forward-Geocoding" */; 171 | buildPhases = ( 172 | 1D60588D0D05DD3D006BFB54 /* Resources */, 173 | 1D60588E0D05DD3D006BFB54 /* Sources */, 174 | 1D60588F0D05DD3D006BFB54 /* Frameworks */, 175 | ); 176 | buildRules = ( 177 | ); 178 | dependencies = ( 179 | ); 180 | name = "Forward-Geocoding"; 181 | productName = "Forward-Geocoding"; 182 | productReference = 1D6058910D05DD3D006BFB54 /* Forward-Geocoding.app */; 183 | productType = "com.apple.product-type.application"; 184 | }; 185 | /* End PBXNativeTarget section */ 186 | 187 | /* Begin PBXProject section */ 188 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 189 | isa = PBXProject; 190 | attributes = { 191 | LastUpgradeCheck = 0420; 192 | }; 193 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Forward-Geocoding" */; 194 | compatibilityVersion = "Xcode 3.2"; 195 | developmentRegion = English; 196 | hasScannedForEncodings = 1; 197 | knownRegions = ( 198 | English, 199 | Japanese, 200 | French, 201 | German, 202 | ); 203 | mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; 204 | projectDirPath = ""; 205 | projectRoot = ""; 206 | targets = ( 207 | 1D6058900D05DD3D006BFB54 /* Forward-Geocoding */, 208 | ); 209 | }; 210 | /* End PBXProject section */ 211 | 212 | /* Begin PBXResourcesBuildPhase section */ 213 | 1D60588D0D05DD3D006BFB54 /* Resources */ = { 214 | isa = PBXResourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | F4786655149387EA0060893E /* MainWindow.xib in Resources */, 218 | F4786658149387EA0060893E /* Forward_GeocodingViewController.xib in Resources */, 219 | ); 220 | runOnlyForDeploymentPostprocessing = 0; 221 | }; 222 | /* End PBXResourcesBuildPhase section */ 223 | 224 | /* Begin PBXSourcesBuildPhase section */ 225 | 1D60588E0D05DD3D006BFB54 /* Sources */ = { 226 | isa = PBXSourcesBuildPhase; 227 | buildActionMask = 2147483647; 228 | files = ( 229 | F4786646149387900060893E /* BSForwardGeocoder.m in Sources */, 230 | F4786647149387900060893E /* BSAddressComponent.m in Sources */, 231 | F4786648149387900060893E /* BSKmlResult.m in Sources */, 232 | F4786649149387900060893E /* BSGoogleV3KmlParser.m in Sources */, 233 | F478664D149387BC0060893E /* CustomPlacemark.m in Sources */, 234 | F4786656149387EA0060893E /* main.m in Sources */, 235 | F478665F149388290060893E /* Forward_GeocodingViewController.m in Sources */, 236 | F4786660149388290060893E /* Forward_GeocodingAppDelegate.m in Sources */, 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | }; 240 | /* End PBXSourcesBuildPhase section */ 241 | 242 | /* Begin XCBuildConfiguration section */ 243 | 1D6058940D05DD3E006BFB54 /* Debug */ = { 244 | isa = XCBuildConfiguration; 245 | buildSettings = { 246 | ALWAYS_SEARCH_USER_PATHS = NO; 247 | COPY_PHASE_STRIP = NO; 248 | GCC_DYNAMIC_NO_PIC = NO; 249 | GCC_OPTIMIZATION_LEVEL = 0; 250 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 251 | GCC_PREFIX_HEADER = "iPad sample/Forward_Geocoding_Prefix.pch"; 252 | INFOPLIST_FILE = "iPad sample/Forward_Geocoding-Info.plist"; 253 | IPHONEOS_DEPLOYMENT_TARGET = 3.0; 254 | PRODUCT_NAME = "Forward-Geocoding"; 255 | SDKROOT = iphoneos; 256 | TARGETED_DEVICE_FAMILY = 2; 257 | }; 258 | name = Debug; 259 | }; 260 | 1D6058950D05DD3E006BFB54 /* Release */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | ALWAYS_SEARCH_USER_PATHS = NO; 264 | COPY_PHASE_STRIP = YES; 265 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 266 | GCC_PREFIX_HEADER = "iPad sample/Forward_Geocoding_Prefix.pch"; 267 | INFOPLIST_FILE = "iPad sample/Forward_Geocoding-Info.plist"; 268 | IPHONEOS_DEPLOYMENT_TARGET = 3.0; 269 | PRODUCT_NAME = "Forward-Geocoding"; 270 | SDKROOT = iphoneos; 271 | TARGETED_DEVICE_FAMILY = 2; 272 | VALIDATE_PRODUCT = YES; 273 | }; 274 | name = Release; 275 | }; 276 | C01FCF4F08A954540054247B /* Debug */ = { 277 | isa = XCBuildConfiguration; 278 | buildSettings = { 279 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 280 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 281 | GCC_C_LANGUAGE_STANDARD = c99; 282 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | IPHONEOS_DEPLOYMENT_TARGET = 3.0; 285 | SDKROOT = iphoneos; 286 | }; 287 | name = Debug; 288 | }; 289 | C01FCF5008A954540054247B /* Release */ = { 290 | isa = XCBuildConfiguration; 291 | buildSettings = { 292 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 293 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 294 | GCC_C_LANGUAGE_STANDARD = c99; 295 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 296 | GCC_WARN_UNUSED_VARIABLE = YES; 297 | IPHONEOS_DEPLOYMENT_TARGET = 3.0; 298 | SDKROOT = iphoneos; 299 | }; 300 | name = Release; 301 | }; 302 | /* End XCBuildConfiguration section */ 303 | 304 | /* Begin XCConfigurationList section */ 305 | 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "Forward-Geocoding" */ = { 306 | isa = XCConfigurationList; 307 | buildConfigurations = ( 308 | 1D6058940D05DD3E006BFB54 /* Debug */, 309 | 1D6058950D05DD3E006BFB54 /* Release */, 310 | ); 311 | defaultConfigurationIsVisible = 0; 312 | defaultConfigurationName = Release; 313 | }; 314 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Forward-Geocoding" */ = { 315 | isa = XCConfigurationList; 316 | buildConfigurations = ( 317 | C01FCF4F08A954540054247B /* Debug */, 318 | C01FCF5008A954540054247B /* Release */, 319 | ); 320 | defaultConfigurationIsVisible = 0; 321 | defaultConfigurationName = Release; 322 | }; 323 | /* End XCConfigurationList section */ 324 | }; 325 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 326 | } 327 | -------------------------------------------------------------------------------- /Forward-Geocoding.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | The iPhone and iPad SDK supports reverse geocoding out of the box. Reverse geocoding means you have a coordinate and want to find out where you are located, for instance, the name of the street you are on. 2 | Forward geocoding means you know the name of a location and want to find the coordinates. 3 | 4 | This API/sample project demonstrate how you can forward geocode using Googles' geocoding service. Documentation of Googles API can be found here: https://developers.google.com/maps/documentation/geocoding/ 5 | 6 | Features: 7 | * No dependencies 8 | * Blocks support 9 | * Works with Google Maps V3 API 10 | 11 | If you are using ARC you need to add "-fno-objc-arc" as compiler flag to the files under "Build Phases" -> "Compile Sources" -> "Compiler Flags". 12 | 13 | The source is unlicensed and 100% free for you to use with whatever you want. Read more about BSForwardGeocoding @ http://blog.sallarp.com/ipad-iphone-forward-geocoding-api-google/ 14 | 15 | -------------------------------------------------------------------------------- /iPad sample/Classes/CustomPlacemark.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-13. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | #import 12 | #import 13 | 14 | @interface CustomPlacemark : NSObject 15 | 16 | @property (nonatomic, readonly) CLLocationCoordinate2D coordinate; 17 | @property (nonatomic, readonly) MKCoordinateRegion coordinateRegion; 18 | @property (nonatomic, copy) NSString *title; 19 | @property (nonatomic, copy) NSString *subtitle; 20 | 21 | -(id)initWithRegion:(MKCoordinateRegion)coordRegion; 22 | @end 23 | -------------------------------------------------------------------------------- /iPad sample/Classes/CustomPlacemark.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-13. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | #import "CustomPlacemark.h" 12 | 13 | 14 | @implementation CustomPlacemark 15 | @synthesize coordinate = _coordinate; 16 | @synthesize coordinateRegion = _coordinateRegion; 17 | @synthesize title = _title; 18 | @synthesize subtitle = _subtitle; 19 | 20 | - (id)initWithRegion:(MKCoordinateRegion)coordRegion 21 | { 22 | if ((self = [super init])) { 23 | _coordinate = coordRegion.center; 24 | _coordinateRegion = coordRegion; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | - (void)dealloc 31 | { 32 | [_title release]; 33 | [_subtitle release]; 34 | [super dealloc]; 35 | } 36 | @end 37 | -------------------------------------------------------------------------------- /iPad sample/Classes/Forward_GeocodingAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-13. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | 12 | #import 13 | 14 | @class Forward_GeocodingViewController; 15 | 16 | @interface Forward_GeocodingAppDelegate : NSObject { 17 | IBOutlet UIWindow *window; 18 | IBOutlet Forward_GeocodingViewController *viewController; 19 | } 20 | 21 | @end 22 | 23 | -------------------------------------------------------------------------------- /iPad sample/Classes/Forward_GeocodingAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-13. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | #import "Forward_GeocodingAppDelegate.h" 12 | #import "Forward_GeocodingViewController.h" 13 | 14 | @implementation Forward_GeocodingAppDelegate 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 17 | 18 | // Override point for customization after app launch 19 | [window addSubview:viewController.view]; 20 | [window makeKeyAndVisible]; 21 | 22 | return YES; 23 | } 24 | 25 | 26 | - (void)dealloc { 27 | [viewController release]; 28 | [window release]; 29 | [super dealloc]; 30 | } 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /iPad sample/Classes/Forward_GeocodingViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-13. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | 12 | #import 13 | #import 14 | #import "BSForwardGeocoder.h" 15 | #import "BSKmlResult.h" 16 | #import "CustomPlacemark.h" 17 | 18 | @interface Forward_GeocodingViewController : UIViewController 19 | 20 | @property (nonatomic, retain) IBOutlet MKMapView *mapView; 21 | @property (nonatomic, retain) IBOutlet UISearchBar *searchBar; 22 | @property (nonatomic, retain) BSForwardGeocoder *forwardGeocoder; 23 | 24 | @end 25 | 26 | 27 | -------------------------------------------------------------------------------- /iPad sample/Classes/Forward_GeocodingViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-13. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | #import "Forward_GeocodingViewController.h" 12 | 13 | @implementation Forward_GeocodingViewController 14 | @synthesize forwardGeocoder = _forwardGeocoder; 15 | @synthesize mapView = _mapView; 16 | @synthesize searchBar = _searchBar; 17 | 18 | - (void)viewDidLoad 19 | { 20 | [super viewDidLoad]; 21 | 22 | self.mapView.showsUserLocation = YES; 23 | self.mapView.delegate = self; 24 | self.searchBar.delegate = self; 25 | } 26 | 27 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 28 | { 29 | return YES; 30 | } 31 | 32 | #pragma mark - BSForwardGeocoderDelegate methods 33 | 34 | - (void)forwardGeocoderConnectionDidFail:(BSForwardGeocoder *)geocoder withErrorMessage:(NSString *)errorMessage 35 | { 36 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error!" 37 | message:errorMessage 38 | delegate:nil 39 | cancelButtonTitle:@"OK" 40 | otherButtonTitles: nil]; 41 | [alert show]; 42 | [alert release]; 43 | } 44 | 45 | 46 | - (void)forwardGeocodingDidSucceed:(BSForwardGeocoder *)geocoder withResults:(NSArray *)results 47 | { 48 | // Add placemarks for each result 49 | for (int i = 0, resultCount = [results count]; i < resultCount; i++) { 50 | BSKmlResult *place = [results objectAtIndex:i]; 51 | 52 | // Add a placemark on the map 53 | CustomPlacemark *placemark = [[[CustomPlacemark alloc] initWithRegion:place.coordinateRegion] autorelease]; 54 | placemark.title = place.address; 55 | placemark.subtitle = place.countryName; 56 | [self.mapView addAnnotation:placemark]; 57 | } 58 | 59 | if ([results count] == 1) { 60 | BSKmlResult *place = [results objectAtIndex:0]; 61 | 62 | // Zoom into the location 63 | [self.mapView setRegion:place.coordinateRegion animated:YES]; 64 | } 65 | 66 | // Dismiss the keyboard 67 | [self.searchBar resignFirstResponder]; 68 | } 69 | 70 | - (void)forwardGeocodingDidFail:(BSForwardGeocoder *)geocoder withErrorCode:(int)errorCode andErrorMessage:(NSString *)errorMessage 71 | { 72 | NSString *message = @""; 73 | 74 | switch (errorCode) { 75 | case G_GEO_BAD_KEY: 76 | message = @"The API key is invalid."; 77 | break; 78 | 79 | case G_GEO_UNKNOWN_ADDRESS: 80 | message = [NSString stringWithFormat:@"Could not find %@", @"searchQuery"]; 81 | break; 82 | 83 | case G_GEO_TOO_MANY_QUERIES: 84 | message = @"Too many queries has been made for this API key."; 85 | break; 86 | 87 | case G_GEO_SERVER_ERROR: 88 | message = @"Server error, please try again."; 89 | break; 90 | 91 | 92 | default: 93 | break; 94 | } 95 | 96 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Information" 97 | message:message 98 | delegate:nil 99 | cancelButtonTitle:@"OK" 100 | otherButtonTitles: nil]; 101 | [alert show]; 102 | [alert release]; 103 | } 104 | 105 | 106 | #pragma mark - UI Events 107 | - (void)searchBarSearchButtonClicked:(UISearchBar *)theSearchBar 108 | { 109 | NSLog(@"Searching for: %@", self.searchBar.text); 110 | if (self.forwardGeocoder == nil) { 111 | self.forwardGeocoder = [[[BSForwardGeocoder alloc] initWithDelegate:self] autorelease]; 112 | } 113 | 114 | // If you want to bias on coordinates pass a bounds object. This example is proof that the "Winnetka" example works (see https://developers.google.com/maps/documentation/geocoding/#Viewports) 115 | CLLocationCoordinate2D southwest, northeast; 116 | southwest.latitude = 34.172684; 117 | southwest.longitude = -118.604794; 118 | northeast.latitude = 34.236144; 119 | northeast.longitude = -118.500938; 120 | BSForwardGeocoderCoordinateBounds *bounds = [BSForwardGeocoderCoordinateBounds boundsWithSouthWest:southwest northEast:northeast]; 121 | 122 | // Forward geocode! 123 | #if NS_BLOCKS_AVAILABLE 124 | [self.forwardGeocoder forwardGeocodeWithQuery:self.searchBar.text regionBiasing:nil viewportBiasing:bounds success:^(NSArray *results) { 125 | [self forwardGeocodingDidSucceed:self.forwardGeocoder withResults:results]; 126 | } failure:^(int status, NSString *errorMessage) { 127 | if (status == G_GEO_NETWORK_ERROR) { 128 | [self forwardGeocoderConnectionDidFail:self.forwardGeocoder withErrorMessage:errorMessage]; 129 | } 130 | else { 131 | [self forwardGeocodingDidFail:self.forwardGeocoder withErrorCode:status andErrorMessage:errorMessage]; 132 | } 133 | }]; 134 | #else 135 | [self.forwardGeocoder forwardGeocodeWithQuery:self.searchBar.text regionBiasing:nil viewportBiasing:nil]; 136 | #endif 137 | } 138 | 139 | #pragma mark - MKMap methods 140 | - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id ) annotation 141 | { 142 | if ([annotation isKindOfClass:[CustomPlacemark class]]) { 143 | MKPinAnnotationView *newAnnotation = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:[annotation title]]; 144 | newAnnotation.pinColor = MKPinAnnotationColorGreen; 145 | newAnnotation.animatesDrop = YES; 146 | newAnnotation.canShowCallout = YES; 147 | newAnnotation.enabled = YES; 148 | 149 | NSLog(@"Created annotation at: %f %f", ((CustomPlacemark*)annotation).coordinate.latitude, ((CustomPlacemark*)annotation).coordinate.longitude); 150 | 151 | [newAnnotation addObserver:self 152 | forKeyPath:@"selected" 153 | options:NSKeyValueObservingOptionNew 154 | context:@"GMAP_ANNOTATION_SELECTED"]; 155 | 156 | [newAnnotation autorelease]; 157 | 158 | return newAnnotation; 159 | } 160 | 161 | return nil; 162 | } 163 | 164 | 165 | - (void)observeValueForKeyPath:(NSString *)keyPath 166 | ofObject:(id)object 167 | change:(NSDictionary *)change 168 | context:(void *)context{ 169 | 170 | NSString *action = (NSString*)context; 171 | 172 | // We only want to zoom to location when the annotation is actaully selected. This will trigger also for when it's deselected 173 | if([[change valueForKey:@"new"] intValue] == 1 && [action isEqualToString:@"GMAP_ANNOTATION_SELECTED"]) { 174 | if ([((MKAnnotationView*) object).annotation isKindOfClass:[CustomPlacemark class]]) { 175 | CustomPlacemark *place = ((MKAnnotationView*) object).annotation; 176 | 177 | // Zoom into the location 178 | [self.mapView setRegion:place.coordinateRegion animated:TRUE]; 179 | NSLog(@"annotation selected: %f %f", ((MKAnnotationView*) object).annotation.coordinate.latitude, ((MKAnnotationView*) object).annotation.coordinate.longitude); 180 | } 181 | } 182 | } 183 | 184 | #pragma mark - Memory management 185 | 186 | - (void)didReceiveMemoryWarning 187 | { 188 | [super didReceiveMemoryWarning]; 189 | } 190 | 191 | - (void)viewDidUnload 192 | { 193 | self.mapView = nil; 194 | self.searchBar = nil; 195 | } 196 | 197 | - (void)dealloc 198 | { 199 | [_mapView release]; 200 | [_searchBar release]; 201 | [_forwardGeocoder release]; 202 | [super dealloc]; 203 | } 204 | 205 | @end 206 | -------------------------------------------------------------------------------- /iPad sample/Forward_Geocoding-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | com.yourcompany.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | NSMainNibFile 28 | MainWindow 29 | 30 | 31 | -------------------------------------------------------------------------------- /iPad sample/Forward_GeocodingViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 800 5 | 10J567 6 | 1305 7 | 1038.35 8 | 462.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 300 12 | 13 | 14 | YES 15 | IBMKMapView 16 | IBUIView 17 | IBUISearchBar 18 | IBProxyObject 19 | 20 | 21 | YES 22 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 23 | 24 | 25 | YES 26 | 27 | YES 28 | 29 | 30 | 31 | 32 | YES 33 | 34 | IBFilesOwner 35 | IBIPadFramework 36 | 37 | 38 | IBFirstResponder 39 | IBIPadFramework 40 | 41 | 42 | 43 | 292 44 | 45 | YES 46 | 47 | 48 | 290 49 | {768, 44} 50 | 51 | 52 | 53 | 3 54 | IBIPadFramework 55 | 56 | IBCocoaTouchFramework 57 | 58 | 59 | 60 | 61 | 274 62 | {{0, 44}, {768, 960}} 63 | 64 | 65 | 66 | YES 67 | YES 68 | IBIPadFramework 69 | 70 | 71 | {{0, 20}, {768, 1004}} 72 | 73 | 74 | 75 | 76 | 3 77 | MQA 78 | 79 | NO 80 | 81 | 2 82 | 83 | IBIPadFramework 84 | 85 | 86 | 87 | 88 | YES 89 | 90 | 91 | view 92 | 93 | 94 | 95 | 3 96 | 97 | 98 | 99 | mapView 100 | 101 | 102 | 103 | 9 104 | 105 | 106 | 107 | searchBar 108 | 109 | 110 | 111 | 10 112 | 113 | 114 | 115 | 116 | YES 117 | 118 | 0 119 | 120 | 121 | 122 | 123 | 124 | -1 125 | 126 | 127 | File's Owner 128 | 129 | 130 | -2 131 | 132 | 133 | 134 | 135 | 2 136 | 137 | 138 | YES 139 | 140 | 141 | 142 | 143 | 144 | 145 | 6 146 | 147 | 148 | 149 | 150 | 7 151 | 152 | 153 | 154 | 155 | 156 | 157 | YES 158 | 159 | YES 160 | -1.CustomClassName 161 | -2.CustomClassName 162 | 2.IBEditorWindowLastContentRect 163 | 2.IBPluginDependency 164 | 6.IBPluginDependency 165 | 7.IBPluginDependency 166 | 167 | 168 | YES 169 | Forward_GeocodingViewController 170 | UIResponder 171 | {{439, 115}, {768, 1024}} 172 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 173 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 174 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 175 | 176 | 177 | 178 | YES 179 | 180 | 181 | 182 | 183 | 184 | YES 185 | 186 | 187 | 188 | 189 | 10 190 | 191 | 192 | 193 | YES 194 | 195 | Forward_GeocodingViewController 196 | UIViewController 197 | 198 | YES 199 | 200 | YES 201 | mapView 202 | searchBar 203 | 204 | 205 | YES 206 | MKMapView 207 | UISearchBar 208 | 209 | 210 | 211 | YES 212 | 213 | YES 214 | mapView 215 | searchBar 216 | 217 | 218 | YES 219 | 220 | mapView 221 | MKMapView 222 | 223 | 224 | searchBar 225 | UISearchBar 226 | 227 | 228 | 229 | 230 | IBProjectSource 231 | ./Classes/Forward_GeocodingViewController.h 232 | 233 | 234 | 235 | 236 | 0 237 | IBIPadFramework 238 | 239 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 240 | 241 | 242 | 243 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 244 | 245 | 246 | YES 247 | 3 248 | 300 249 | 250 | 251 | -------------------------------------------------------------------------------- /iPad sample/Forward_Geocoding_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Forward-Geocoding' target in the 'Forward-Geocoding' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import 8 | #endif 9 | -------------------------------------------------------------------------------- /iPad sample/MainWindow.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 800 5 | 10C540 6 | 759 7 | 1038.25 8 | 458.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 77 12 | 13 | 14 | YES 15 | 16 | 17 | 18 | YES 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | YES 23 | 24 | YES 25 | 26 | 27 | YES 28 | 29 | 30 | 31 | YES 32 | 33 | IBFilesOwner 34 | IBCocoaTouchFramework 35 | 36 | 37 | IBFirstResponder 38 | IBCocoaTouchFramework 39 | 40 | 41 | 42 | 292 43 | {768, 1024} 44 | 45 | 46 | 1 47 | MSAxIDEAA 48 | 49 | NO 50 | NO 51 | 52 | 2 53 | 54 | IBIPadFramework 55 | 56 | 57 | IBIPadFramework 58 | 59 | 60 | Forward_GeocodingViewController 61 | 62 | IBIPadFramework 63 | 64 | 65 | 66 | 67 | YES 68 | 69 | 70 | viewController 71 | 72 | 73 | 74 | 8 75 | 76 | 77 | 78 | delegate 79 | 80 | 81 | 82 | 9 83 | 84 | 85 | 86 | window 87 | 88 | 89 | 90 | 10 91 | 92 | 93 | 94 | 95 | YES 96 | 97 | 0 98 | 99 | 100 | 101 | 102 | 103 | -1 104 | 105 | 106 | File's Owner 107 | 108 | 109 | -2 110 | 111 | 112 | 113 | 114 | 2 115 | 116 | 117 | 118 | 119 | 6 120 | 121 | 122 | Forward_Geocoding App Delegate 123 | 124 | 125 | 7 126 | 127 | 128 | 129 | 130 | 131 | 132 | YES 133 | 134 | YES 135 | -1.CustomClassName 136 | -2.CustomClassName 137 | 2.IBEditorWindowLastContentRect 138 | 2.IBPluginDependency 139 | 6.CustomClassName 140 | 6.IBPluginDependency 141 | 7.CustomClassName 142 | 7.IBEditorWindowLastContentRect 143 | 7.IBPluginDependency 144 | 145 | 146 | YES 147 | UIApplication 148 | UIResponder 149 | {{200, 132}, {768, 1024}} 150 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 151 | Forward_GeocodingAppDelegate 152 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 153 | Forward_GeocodingViewController 154 | {{512, 351}, {320, 480}} 155 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 156 | 157 | 158 | 159 | YES 160 | 161 | 162 | YES 163 | 164 | 165 | 166 | 167 | YES 168 | 169 | 170 | YES 171 | 172 | 173 | 174 | 10 175 | 176 | 177 | 178 | YES 179 | 180 | Forward_GeocodingAppDelegate 181 | NSObject 182 | 183 | YES 184 | 185 | YES 186 | viewController 187 | window 188 | 189 | 190 | YES 191 | Forward_GeocodingViewController 192 | UIWindow 193 | 194 | 195 | 196 | IBProjectSource 197 | Classes/Forward_GeocodingAppDelegate.h 198 | 199 | 200 | 201 | Forward_GeocodingViewController 202 | UIViewController 203 | 204 | IBProjectSource 205 | Classes/Forward_GeocodingViewController.h 206 | 207 | 208 | 209 | 210 | YES 211 | 212 | NSObject 213 | 214 | IBFrameworkSource 215 | Foundation.framework/Headers/NSError.h 216 | 217 | 218 | 219 | NSObject 220 | 221 | IBFrameworkSource 222 | Foundation.framework/Headers/NSFileManager.h 223 | 224 | 225 | 226 | NSObject 227 | 228 | IBFrameworkSource 229 | Foundation.framework/Headers/NSKeyValueCoding.h 230 | 231 | 232 | 233 | NSObject 234 | 235 | IBFrameworkSource 236 | Foundation.framework/Headers/NSKeyValueObserving.h 237 | 238 | 239 | 240 | NSObject 241 | 242 | IBFrameworkSource 243 | Foundation.framework/Headers/NSKeyedArchiver.h 244 | 245 | 246 | 247 | NSObject 248 | 249 | IBFrameworkSource 250 | Foundation.framework/Headers/NSNetServices.h 251 | 252 | 253 | 254 | NSObject 255 | 256 | IBFrameworkSource 257 | Foundation.framework/Headers/NSObject.h 258 | 259 | 260 | 261 | NSObject 262 | 263 | IBFrameworkSource 264 | Foundation.framework/Headers/NSPort.h 265 | 266 | 267 | 268 | NSObject 269 | 270 | IBFrameworkSource 271 | Foundation.framework/Headers/NSRunLoop.h 272 | 273 | 274 | 275 | NSObject 276 | 277 | IBFrameworkSource 278 | Foundation.framework/Headers/NSStream.h 279 | 280 | 281 | 282 | NSObject 283 | 284 | IBFrameworkSource 285 | Foundation.framework/Headers/NSThread.h 286 | 287 | 288 | 289 | NSObject 290 | 291 | IBFrameworkSource 292 | Foundation.framework/Headers/NSURL.h 293 | 294 | 295 | 296 | NSObject 297 | 298 | IBFrameworkSource 299 | Foundation.framework/Headers/NSURLConnection.h 300 | 301 | 302 | 303 | NSObject 304 | 305 | IBFrameworkSource 306 | Foundation.framework/Headers/NSXMLParser.h 307 | 308 | 309 | 310 | NSObject 311 | 312 | IBFrameworkSource 313 | UIKit.framework/Headers/UIAccessibility.h 314 | 315 | 316 | 317 | NSObject 318 | 319 | IBFrameworkSource 320 | UIKit.framework/Headers/UINibLoading.h 321 | 322 | 323 | 324 | NSObject 325 | 326 | IBFrameworkSource 327 | UIKit.framework/Headers/UIResponder.h 328 | 329 | 330 | 331 | UIApplication 332 | UIResponder 333 | 334 | IBFrameworkSource 335 | UIKit.framework/Headers/UIApplication.h 336 | 337 | 338 | 339 | UIResponder 340 | NSObject 341 | 342 | 343 | 344 | UIResponder 345 | 346 | IBFrameworkSource 347 | UIKit.framework/Headers/UITextInput.h 348 | 349 | 350 | 351 | UISearchBar 352 | UIView 353 | 354 | IBFrameworkSource 355 | UIKit.framework/Headers/UISearchBar.h 356 | 357 | 358 | 359 | UISearchDisplayController 360 | NSObject 361 | 362 | IBFrameworkSource 363 | UIKit.framework/Headers/UISearchDisplayController.h 364 | 365 | 366 | 367 | UIView 368 | 369 | IBFrameworkSource 370 | UIKit.framework/Headers/UITextField.h 371 | 372 | 373 | 374 | UIView 375 | UIResponder 376 | 377 | IBFrameworkSource 378 | UIKit.framework/Headers/UIView.h 379 | 380 | 381 | 382 | UIViewController 383 | 384 | IBFrameworkSource 385 | UIKit.framework/Headers/UINavigationController.h 386 | 387 | 388 | 389 | UIViewController 390 | 391 | IBFrameworkSource 392 | UIKit.framework/Headers/UISplitViewController.h 393 | 394 | 395 | 396 | UIViewController 397 | 398 | IBFrameworkSource 399 | UIKit.framework/Headers/UITabBarController.h 400 | 401 | 402 | 403 | UIViewController 404 | UIResponder 405 | 406 | IBFrameworkSource 407 | UIKit.framework/Headers/UIViewController.h 408 | 409 | 410 | 411 | UIWindow 412 | UIView 413 | 414 | IBFrameworkSource 415 | UIKit.framework/Headers/UIWindow.h 416 | 417 | 418 | 419 | 420 | 0 421 | IBIPadFramework 422 | 423 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 424 | 425 | 426 | 427 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 428 | 429 | 430 | YES 431 | Forward-Geocoding.xcodeproj 432 | 3 433 | 77 434 | 435 | 436 | 437 | -------------------------------------------------------------------------------- /iPad sample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Björn Sållarp on 2010-03-13. 3 | // NO Copyright 2010 MightyLittle Industries. NO rights reserved. 4 | // 5 | // Use this code any way you like. If you do like it, please 6 | // link to my blog and/or write a friendly comment. Thank you! 7 | // 8 | // Read my blog @ http://blog.sallarp.com 9 | // 10 | 11 | #import 12 | 13 | int main(int argc, char *argv[]) { 14 | 15 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 16 | int retVal = UIApplicationMain(argc, argv, nil, nil); 17 | [pool release]; 18 | return retVal; 19 | } 20 | --------------------------------------------------------------------------------