Skip to content

Commit 0f92b3b

Browse files
committed
Merge pull request #28 from mapbox/1ec5-requestkit
Rewrote request logic based on RequestKit
2 parents 1ac8438 + 31e68a1 commit 0f92b3b

File tree

6 files changed

+197
-93
lines changed

6 files changed

+197
-93
lines changed

MapboxGeocoder.xcodeproj/project.pbxproj

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@
88

99
/* Begin PBXBuildFile section */
1010
8DF260A67CA4C55F8FA7CAA0 /* Pods_MapboxGeocoderTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9CD6EA86BBE0D7DE16654CB4 /* Pods_MapboxGeocoderTests.framework */; };
11+
9FB47CA319B32DD7142B5830 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6953F60F050AE274E006CB85 /* Pods.framework */; };
1112
DA2E03F01CB0FDB400D1269A /* MBPlacemark.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2E03EF1CB0FDB400D1269A /* MBPlacemark.swift */; };
1213
DA2E03F21CB0FE0200D1269A /* MBRectangularRegion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2E03F11CB0FE0200D1269A /* MBRectangularRegion.swift */; };
14+
DA2E03F71CB0FFD800D1269A /* MBGeocoderConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2E03F61CB0FFD800D1269A /* MBGeocoderConfiguration.swift */; };
15+
DA2E03F91CB0FFF700D1269A /* RequestKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2E03F81CB0FFF700D1269A /* RequestKit.framework */; };
16+
DA2E03FB1CB1009200D1269A /* MBGeocoderRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2E03FA1CB1009200D1269A /* MBGeocoderRouter.swift */; };
1317
DD342B5619A140EE00219F77 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD342B5519A140EE00219F77 /* AppDelegate.swift */; };
1418
DD342B5819A140EE00219F77 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD342B5719A140EE00219F77 /* ViewController.swift */; };
1519
DDC2295C1A36074F006BE405 /* MapboxGeocoder.h in Headers */ = {isa = PBXBuildFile; fileRef = DDC229581A36073B006BE405 /* MapboxGeocoder.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -93,6 +97,9 @@
9397
D9281D748078BEB61AACF246 /* Pods_Unit_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Unit_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9498
DA2E03EF1CB0FDB400D1269A /* MBPlacemark.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MBPlacemark.swift; sourceTree = "<group>"; };
9599
DA2E03F11CB0FE0200D1269A /* MBRectangularRegion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MBRectangularRegion.swift; sourceTree = "<group>"; };
100+
DA2E03F61CB0FFD800D1269A /* MBGeocoderConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MBGeocoderConfiguration.swift; sourceTree = "<group>"; };
101+
DA2E03F81CB0FFF700D1269A /* RequestKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RequestKit.framework; path = "Pods/../build/Debug-iphoneos/RequestKit.framework"; sourceTree = "<group>"; };
102+
DA2E03FA1CB1009200D1269A /* MBGeocoderRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MBGeocoderRouter.swift; sourceTree = "<group>"; };
96103
DD342B5019A140EE00219F77 /* Geocoder (Swift).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Geocoder (Swift).app"; sourceTree = BUILT_PRODUCTS_DIR; };
97104
DD342B5419A140EE00219F77 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
98105
DD342B5519A140EE00219F77 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -121,13 +128,15 @@
121128
buildActionMask = 2147483647;
122129
files = (
123130
DDC2471819A1C3B40054B0C0 /* MapboxGeocoder.framework in Frameworks */,
131+
9FB47CA319B32DD7142B5830 /* Pods.framework in Frameworks */,
124132
);
125133
runOnlyForDeploymentPostprocessing = 0;
126134
};
127135
DDC2470019A1C3B40054B0C0 /* Frameworks */ = {
128136
isa = PBXFrameworksBuildPhase;
129137
buildActionMask = 2147483647;
130138
files = (
139+
DA2E03F91CB0FFF700D1269A /* RequestKit.framework in Frameworks */,
131140
);
132141
runOnlyForDeploymentPostprocessing = 0;
133142
};
@@ -166,13 +175,23 @@
166175
4CFB56C6CFCDF74D848CC98C /* Frameworks */ = {
167176
isa = PBXGroup;
168177
children = (
178+
DA2E03F81CB0FFF700D1269A /* RequestKit.framework */,
169179
D9281D748078BEB61AACF246 /* Pods_Unit_Tests.framework */,
170180
6953F60F050AE274E006CB85 /* Pods.framework */,
171181
9CD6EA86BBE0D7DE16654CB4 /* Pods_MapboxGeocoderTests.framework */,
172182
);
173183
name = Frameworks;
174184
sourceTree = "<group>";
175185
};
186+
DA2E03F51CB0FFC500D1269A /* Router */ = {
187+
isa = PBXGroup;
188+
children = (
189+
DA2E03F61CB0FFD800D1269A /* MBGeocoderConfiguration.swift */,
190+
DA2E03FA1CB1009200D1269A /* MBGeocoderRouter.swift */,
191+
);
192+
name = Router;
193+
sourceTree = "<group>";
194+
};
176195
DD342B4719A140EE00219F77 = {
177196
isa = PBXGroup;
178197
children = (
@@ -221,6 +240,7 @@
221240
DDC229591A36073B006BE405 /* MBGeocoder.swift */,
222241
DA2E03EF1CB0FDB400D1269A /* MBPlacemark.swift */,
223242
DA2E03F11CB0FE0200D1269A /* MBRectangularRegion.swift */,
243+
DA2E03F51CB0FFC500D1269A /* Router */,
224244
DDC2470619A1C3B40054B0C0 /* Supporting Files */,
225245
);
226246
path = MapboxGeocoder;
@@ -293,10 +313,13 @@
293313
isa = PBXNativeTarget;
294314
buildConfigurationList = DD342B6C19A140EE00219F77 /* Build configuration list for PBXNativeTarget "Example (Swift)" */;
295315
buildPhases = (
316+
E03AB5375E2A0105D7C52F4C /* Check Pods Manifest.lock */,
296317
DD342B4C19A140EE00219F77 /* Sources */,
297318
DD342B4D19A140EE00219F77 /* Frameworks */,
298319
DD342B4E19A140EE00219F77 /* Resources */,
299320
DDC2471919A1C3B40054B0C0 /* Embed Frameworks */,
321+
75F39693BBF5C90FFDC01998 /* Embed Pods Frameworks */,
322+
E701C4F0292AE0B9460ADB36 /* Copy Pods Resources */,
300323
);
301324
buildRules = (
302325
);
@@ -477,6 +500,21 @@
477500
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-MapboxGeocoderTests/Pods-MapboxGeocoderTests-resources.sh\"\n";
478501
showEnvVarsInLog = 0;
479502
};
503+
75F39693BBF5C90FFDC01998 /* Embed Pods Frameworks */ = {
504+
isa = PBXShellScriptBuildPhase;
505+
buildActionMask = 2147483647;
506+
files = (
507+
);
508+
inputPaths = (
509+
);
510+
name = "Embed Pods Frameworks";
511+
outputPaths = (
512+
);
513+
runOnlyForDeploymentPostprocessing = 0;
514+
shellPath = /bin/sh;
515+
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
516+
showEnvVarsInLog = 0;
517+
};
480518
CD3F1CAEDE243BEE7EC3EFEF /* Embed Pods Frameworks */ = {
481519
isa = PBXShellScriptBuildPhase;
482520
buildActionMask = 2147483647;
@@ -492,6 +530,36 @@
492530
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-MapboxGeocoderTests/Pods-MapboxGeocoderTests-frameworks.sh\"\n";
493531
showEnvVarsInLog = 0;
494532
};
533+
E03AB5375E2A0105D7C52F4C /* Check Pods Manifest.lock */ = {
534+
isa = PBXShellScriptBuildPhase;
535+
buildActionMask = 2147483647;
536+
files = (
537+
);
538+
inputPaths = (
539+
);
540+
name = "Check Pods Manifest.lock";
541+
outputPaths = (
542+
);
543+
runOnlyForDeploymentPostprocessing = 0;
544+
shellPath = /bin/sh;
545+
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
546+
showEnvVarsInLog = 0;
547+
};
548+
E701C4F0292AE0B9460ADB36 /* Copy Pods Resources */ = {
549+
isa = PBXShellScriptBuildPhase;
550+
buildActionMask = 2147483647;
551+
files = (
552+
);
553+
inputPaths = (
554+
);
555+
name = "Copy Pods Resources";
556+
outputPaths = (
557+
);
558+
runOnlyForDeploymentPostprocessing = 0;
559+
shellPath = /bin/sh;
560+
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
561+
showEnvVarsInLog = 0;
562+
};
495563
/* End PBXShellScriptBuildPhase section */
496564

497565
/* Begin PBXSourcesBuildPhase section */
@@ -511,6 +579,8 @@
511579
DA2E03F21CB0FE0200D1269A /* MBRectangularRegion.swift in Sources */,
512580
DDC2295E1A360843006BE405 /* MBGeocoder.swift in Sources */,
513581
DA2E03F01CB0FDB400D1269A /* MBPlacemark.swift in Sources */,
582+
DA2E03FB1CB1009200D1269A /* MBGeocoderRouter.swift in Sources */,
583+
DA2E03F71CB0FFD800D1269A /* MBGeocoderConfiguration.swift in Sources */,
514584
);
515585
runOnlyForDeploymentPostprocessing = 0;
516586
};
@@ -640,6 +710,7 @@
640710
};
641711
DD342B6D19A140EE00219F77 /* Debug */ = {
642712
isa = XCBuildConfiguration;
713+
baseConfigurationReference = A7FEE3C3AC9D553F9763CB06 /* Pods.debug.xcconfig */;
643714
buildSettings = {
644715
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
645716
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
@@ -652,6 +723,7 @@
652723
};
653724
DD342B6E19A140EE00219F77 /* Release */ = {
654725
isa = XCBuildConfiguration;
726+
baseConfigurationReference = CC09570CD1A6D11014400590 /* Pods.release.xcconfig */;
655727
buildSettings = {
656728
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
657729
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;

MapboxGeocoder/MBGeocoder.swift

Lines changed: 48 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -10,120 +10,79 @@ public func ==(left: CLLocationCoordinate2D, right: CLLocationCoordinate2D) -> B
1010
return (left.latitude == right.latitude && left.longitude == right.longitude)
1111
}
1212

13-
// MARK: - Geocoder
13+
public let MBGeocoderErrorDomain = "MBGeocoderErrorDomain"
1414

15-
public class MBGeocoder: NSObject,
16-
NSURLConnectionDelegate,
17-
NSURLConnectionDataDelegate {
15+
public class MBGeocoder: NSObject {
1816

19-
// MARK: - Setup
20-
21-
private let accessToken: NSString
17+
private let configuration: MBGeocoderConfiguration
2218

23-
public init(accessToken: NSString) {
24-
self.accessToken = accessToken
25-
super.init()
19+
public init(accessToken: String) {
20+
configuration = MBGeocoderConfiguration(accessToken)
2621
}
27-
28-
private var connection: NSURLConnection?
29-
private var completionHandler: MBGeocodeCompletionHandler?
30-
private var receivedData: NSMutableData?
3122

32-
private let MBGeocoderErrorDomain = "MBGeocoderErrorDomain"
33-
34-
private enum MBGeocoderErrorCode: Int {
35-
case ConnectionError = -1000
36-
case HTTPError = -1001
37-
case ParseError = -1002
23+
private var task: NSURLSessionDataTask?
24+
25+
private var errorForSimultaneousRequests: NSError {
26+
let userInfo = [
27+
NSLocalizedFailureReasonErrorKey: "Cannot geocode on an MBGeocoder object that is already geocoding.",
28+
]
29+
return NSError(domain: MBGeocoderErrorDomain, code: -1, userInfo: userInfo)
3830
}
3931

40-
// MARK: - Public API
41-
4232
public var geocoding: Bool {
43-
return (self.connection != nil)
33+
return task?.state == .Running
4434
}
4535

4636
public func reverseGeocodeLocation(location: CLLocation, completionHandler: MBGeocodeCompletionHandler) {
47-
if !self.geocoding {
48-
self.completionHandler = completionHandler
49-
let requestString = String(format: "https://api.mapbox.com/geocoding/v5/mapbox.places/%.5f,%.5f.json?access_token=%@",
50-
round(location.coordinate.longitude * 1e5) / 1e5,
51-
round(location.coordinate.latitude * 1e5) / 1e5, accessToken)
52-
let request = NSURLRequest(URL: NSURL(string: requestString)!)
53-
self.connection = NSURLConnection(request: request, delegate: self)
37+
guard !geocoding else {
38+
completionHandler(nil, errorForSimultaneousRequests)
39+
return
5440
}
41+
42+
let query = String(format: "%.5f,%.5f", location.coordinate.longitude, location.coordinate.latitude)
43+
let router = MBGeocoderRouter.V5(configuration, false, query, nil, nil, nil, nil)
44+
task = taskWithRouter(router, completionHandler: completionHandler)
5545
}
5646

5747
// public func geocodeAddressDictionary(addressDictionary: [NSObject : AnyObject],
5848
// completionHandler: MBGeocodeCompletionHandler)
5949

60-
public func geocodeAddressString(addressString: String, proximity: CLLocationCoordinate2D? = nil, completionHandler: MBGeocodeCompletionHandler) {
61-
if !self.geocoding {
62-
self.completionHandler = completionHandler
63-
var requestString = "https://api.mapbox.com/geocoding/v5/mapbox.places/" +
64-
addressString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet())! +
65-
".json?access_token=\(accessToken)"
66-
if let proximityCoordinate = proximity {
67-
requestString += String(format: "&proximity=%.3f,%.3f",
68-
round(proximityCoordinate.longitude * 1e3) / 1e3,
69-
round(proximityCoordinate.latitude * 1e3) / 1e3)
70-
}
71-
let request = NSURLRequest(URL: NSURL(string: requestString)!)
72-
self.connection = NSURLConnection(request: request, delegate: self)
50+
public func geocodeAddressString(addressString: String, nearLocation focusLocation: CLLocation? = nil, inCountries ISOCountryCodes: [String]? = nil, completionHandler: MBGeocodeCompletionHandler) {
51+
guard !geocoding else {
52+
completionHandler(nil, errorForSimultaneousRequests)
53+
return
7354
}
55+
56+
let router = MBGeocoderRouter.V5(configuration, false, addressString, ISOCountryCodes, focusLocation?.coordinate, nil, nil)
57+
task = taskWithRouter(router, completionHandler: completionHandler)
7458
}
7559

7660
// public func geocodeAddressString(addressString: String, inRegion region: CLRegion, completionHandler: MBGeocodeCompletionHandler)
77-
78-
public func cancelGeocode() {
79-
self.connection?.cancel()
80-
self.connection = nil
81-
}
8261

83-
// MARK: - NSURLConnection Delegates
84-
85-
public func connection(connection: NSURLConnection, didFailWithError error: NSError) {
86-
self.connection = nil
87-
self.completionHandler?(nil, NSError(domain: MBGeocoderErrorDomain,
88-
code: MBGeocoderErrorCode.ConnectionError.rawValue,
89-
userInfo: error.userInfo))
90-
}
91-
92-
public func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) {
93-
let statusCode = (response as! NSHTTPURLResponse).statusCode
94-
if statusCode != 200 {
95-
self.connection?.cancel()
96-
self.connection = nil
97-
self.completionHandler?(nil, NSError(domain: MBGeocoderErrorDomain,
98-
code: MBGeocoderErrorCode.HTTPError.rawValue,
99-
userInfo: [ NSLocalizedDescriptionKey: "Received HTTP status code \(statusCode)" ]))
100-
} else {
101-
self.receivedData = NSMutableData()
102-
}
103-
}
104-
105-
public func connection(connection: NSURLConnection, didReceiveData data: NSData) {
106-
self.receivedData!.appendData(data)
107-
}
108-
109-
public func connectionDidFinishLoading(connection: NSURLConnection) {
110-
if let response = (try? NSJSONSerialization.JSONObjectWithData(self.receivedData!, options: [])) as? JSON {
111-
if let features = response["features"] as? [JSON] {
112-
var results: [MBPlacemark] = []
113-
for feature in features {
114-
if let placemark = MBPlacemark(featureJSON: feature) {
115-
results.append(placemark)
116-
}
62+
private func taskWithRouter(router: MBGeocoderRouter, completionHandler completion: MBGeocodeCompletionHandler) -> NSURLSessionDataTask? {
63+
return router.loadJSON(JSON.self) { [weak self] (json, error) in
64+
guard let dataTaskSelf = self where dataTaskSelf.task?.state == .Completed
65+
else {
66+
return
67+
}
68+
69+
guard error == nil && json != nil else {
70+
dispatch_sync(dispatch_get_main_queue()) {
71+
completion(nil, error as? NSError)
11772
}
118-
self.completionHandler?(results, nil)
119-
} else {
120-
self.completionHandler?([], nil)
73+
return
74+
}
75+
76+
let features = json!["features"] as! [JSON]
77+
let placemarks = features.flatMap { MBPlacemark(featureJSON: $0) }
78+
79+
dispatch_sync(dispatch_get_main_queue()) {
80+
completion(placemarks, error as? NSError)
12181
}
122-
} else {
123-
self.completionHandler?(nil, NSError(domain: MBGeocoderErrorDomain,
124-
code: MBGeocoderErrorCode.ParseError.rawValue,
125-
userInfo: [ NSLocalizedDescriptionKey: "Unable to parse results" ]))
12682
}
12783
}
12884

85+
public func cancelGeocode() {
86+
task?.cancel()
87+
}
12988
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import Foundation
2+
import RequestKit
3+
4+
internal struct MBGeocoderConfiguration: Configuration {
5+
internal var apiEndpoint: String = "https://api.mapbox.com"
6+
internal var accessToken: String?
7+
8+
internal init(_ accessToken: String) {
9+
self.accessToken = accessToken
10+
}
11+
}

0 commit comments

Comments
 (0)