/
DJGeocoder.m
158 lines (136 loc) · 5.14 KB
/
DJGeocoder.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//
// DJGeocoder.m
//
//
// Created by Derrick Jones on 3/23/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "DJGeocoder.h"
@implementation DJGeocoder
@synthesize streetAddress, city, state, country, delegate;
- (NSString *)urlEncodedAddress {
//build up string component by component, separated by commas.
//This needs work
NSMutableString *address = [[NSMutableString alloc] init];
if (streetAddress) {
[address appendString:[streetAddress stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
if (city) {
[address appendFormat:@",%@", [city stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
if (state) {
[address appendFormat:@",%@", [state stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
if (country) {
[address appendFormat:@",%@", [country stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
return [address autorelease];
}
#pragma mark -
#pragma mark Public API
- (void)startAsynchronousRequest{
// build URL for request with Address (pretend we have it for now)
NSString *address = [self urlEncodedAddress];
NSString *urlString = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/xml?address=%@&sensor=true&",address];
// now that we have a well-formed url string, let's get our request
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
[connection start];
}
#pragma mark -
#pragma mark NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
if (!xmlData) {
xmlData = [[NSMutableData alloc] init];
}
[xmlData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"%@", @"Failed!");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// loading finished, now can parse xml
NSString *xmlString = [[NSString alloc] initWithBytes:[xmlData bytes] length:[xmlData length] encoding:NSUTF8StringEncoding];
[xmlString release];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
parser.delegate = self;
[parser parse];
}
#pragma mark -
#pragma mark NSXMLParserDelegate
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if ([elementName isEqual:@"status"]) {
parsingStatus = YES;
} else if ([elementName isEqual:@"location"]) {
parsingLocation = YES;
} else if ([elementName isEqual:@"lat"]) {
parsingLatitude = YES;
} else if ([elementName isEqual:@"lng"]) {
parsingLongitude = YES;
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqual:@"status"]) {
parsingStatus = NO;
NSLog(@"status: %@", currentParseString);
// if status is not OK, probably need to abort parsing and send message
[currentParseString release];
currentParseString = nil;
} else if ([elementName isEqual:@"location"]) {
parsingLocation = NO;
// never built string for location, so no need to reset it
} else if (parsingLocation && [elementName isEqual:@"lat"]) {
parsingLatitude = NO;
NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
theLat = [formatter numberFromString:currentParseString];
[currentParseString release];
currentParseString = nil;
} else if (parsingLocation && [elementName isEqual:@"lng"]) {
parsingLongitude = NO;
NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
theLng = [formatter numberFromString:currentParseString];
[currentParseString release];
currentParseString = nil;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
// only build up string when parsing one of the fields we are interested in
// Interested in: Request status, as well as latitude/longitude, but only when child of location
// http://code.google.com/apis/maps/documentation/geocoding/#XML
if (parsingStatus || (parsingLocation && (parsingLatitude || parsingLongitude))) {
if (!currentParseString) {
currentParseString = [[NSMutableString alloc] init];
}
[currentParseString appendString:string];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
// call delegate method with latitude and longitude.
// probably use details NSDictionary to provide more info at some point
if ([delegate respondsToSelector:@selector(geocoder:didSucceedWithLatitude:Longitude:Details:)]) {
[delegate geocoder:self didSucceedWithLatitude:theLat Longitude:theLng Details:nil];
}
[parser release];
}
//FIXME: take care of parser errors
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
}
#pragma mark -
#pragma mark Memory Management
- (void)dealloc {
[delegate release];
[streetAddress release];
[city release];
[state release];
[country release];
[xmlData release];
[theLat release];
[theLng release];
[currentParseString release];
[super dealloc];
}
@end