0001 // 0002 // SearchManager.swift 0003 // PlayMap 0004 // 0005 // Created by Matt on 11/13/15. 0006 // Copyright © 2015 Mapzen. All rights reserved. 0007 // 0008 0009 import Foundation 0010 0011 public final class PeliasSearchManager{ 0012 0013 //! Singleton access 0014 static let sharedInstance
PeliasAutocompleteConfig.swift:19 var urlEndpoint = NSURL.init(string: "/v1/autocomplete", relativeToURL: PeliasSearchManager.sharedInstance.baseUrl)!PeliasAutocompleteConfig.swift:43 apiKey = PeliasSearchManager.sharedInstance.apiKeyPeliasPlaceConfig.swift:13 var urlEndpoint = NSURL.init(string: "/v1/place", relativeToURL: PeliasSearchManager.sharedInstance.baseUrl)!PeliasPlaceConfig.swift:34 apiKey = PeliasSearchManager.sharedInstance.apiKeyPeliasReverseGeoConfig.swift:12 var urlEndpoint = NSURL.init(string: "/v1/reverse", relativeToURL: PeliasSearchManager.sharedInstance.baseUrl)!PeliasReverseGeoConfig.swift:69 apiKey = PeliasSearchManager.sharedInstance.apiKeyPeliasSearchConfigObject.swift:13 var urlEndpoint = NSURL.init(string: "/v1/search", relativeToURL: PeliasSearchManager.sharedInstance.baseUrl)!PeliasSearchConfigObject.swift:100 apiKey = PeliasSearchManager.sharedInstance.apiKeyPeliasSearchManager.swift:14 static let sharedInstance = PeliasSearchManager()= PeliasSearchManager() 0015 private let operationQueue
PeliasAutocompleteConfig.swift:19 var urlEndpoint = NSURL.init(string: "/v1/autocomplete", relativeToURL: PeliasSearchManager.sharedInstance.baseUrl)!PeliasAutocompleteConfig.swift:43 apiKey = PeliasSearchManager.sharedInstance.apiKeyPeliasPlaceConfig.swift:13 var urlEndpoint = NSURL.init(string: "/v1/place", relativeToURL: PeliasSearchManager.sharedInstance.baseUrl)!PeliasPlaceConfig.swift:34 apiKey = PeliasSearchManager.sharedInstance.apiKeyPeliasReverseGeoConfig.swift:12 var urlEndpoint = NSURL.init(string: "/v1/reverse", relativeToURL: PeliasSearchManager.sharedInstance.baseUrl)!PeliasReverseGeoConfig.swift:69 apiKey = PeliasSearchManager.sharedInstance.apiKeyPeliasSearchConfigObject.swift:13 var urlEndpoint = NSURL.init(string: "/v1/search", relativeToURL: PeliasSearchManager.sharedInstance.baseUrl)!PeliasSearchConfigObject.swift:100 apiKey = PeliasSearchManager.sharedInstance.apiKey= NSOperationQueue() 0016 private let autocompleteOperationQueue
PeliasSearchManager.swift:24 operationQueue.maxConcurrentOperationCount = 4PeliasSearchManager.swift:47 self.operationQueue.cancelAllOperations()PeliasSearchManager.swift:56 operationQueue.addOperation(searchOp)= NSOperationQueue() 0017 private var autocompleteQueryTimer
PeliasSearchManager.swift:25 autocompleteOperationQueue.maxConcurrentOperationCount = 1PeliasSearchManager.swift:48 self.autocompleteOperationQueue.cancelAllOperations()PeliasSearchManager.swift:85 autocompleteOperationQueue.addOperation(operation): NSTimer? 0018 internal var queuedAutocompleteOp
PeliasSearchManager.swift:72 if autocompleteQueryTimer == nil {PeliasSearchManager.swift:87 autocompleteQueryTimer = NSTimer.scheduledTimerWithTimeInterval(autocompleteTimeDelay, target: self, selector: "autocompleteTimerExecute", userInfo: nil, repeats: false)PeliasSearchManager.swift:91 autocompleteQueryTimer = nil: PeliasOperation? 0019 public var autocompleteTimeDelay
PeliasSearchManager.swift:69 queuedAutocompleteOp = operationPeliasSearchManager.swift:82 if let operation = queuedAutocompleteOp {PeliasSearchManager.swift:86 queuedAutocompleteOp = nil: Double = 0.0 //In seconds 0020 var apiKey
PeliasSearchManager.swift:64 if (autocompleteTimeDelay <= 0) {PeliasSearchManager.swift:87 autocompleteQueryTimer = NSTimer.scheduledTimerWithTimeInterval(autocompleteTimeDelay, target: self, selector: "autocompleteTimerExecute", userInfo: nil, repeats: false): String? 0021 var baseUrl
PeliasAutocompleteConfig.swift:43 apiKey = PeliasSearchManager.sharedInstance.apiKeyPeliasPlaceConfig.swift:34 apiKey = PeliasSearchManager.sharedInstance.apiKeyPeliasReverseGeoConfig.swift:69 apiKey = PeliasSearchManager.sharedInstance.apiKeyPeliasSearchConfigObject.swift:100 apiKey = PeliasSearchManager.sharedInstance.apiKey: NSURL 0022 0023 private init
PeliasAutocompleteConfig.swift:19 var urlEndpoint = NSURL.init(string: "/v1/autocomplete", relativeToURL: PeliasSearchManager.sharedInstance.baseUrl)!PeliasPlaceConfig.swift:13 var urlEndpoint = NSURL.init(string: "/v1/place", relativeToURL: PeliasSearchManager.sharedInstance.baseUrl)!PeliasReverseGeoConfig.swift:12 var urlEndpoint = NSURL.init(string: "/v1/reverse", relativeToURL: PeliasSearchManager.sharedInstance.baseUrl)!PeliasSearchConfigObject.swift:13 var urlEndpoint = NSURL.init(string: "/v1/search", relativeToURL: PeliasSearchManager.sharedInstance.baseUrl)!PeliasSearchManager.swift:26 baseUrl = NSURL.init(string: "https://search.mapzen.com")! // Force the unwrap because we must have a base URL to operate() { 0024 operationQueue.maxConcurrentOperationCount = 4 0025 autocompleteOperationQueue.maxConcurrentOperationCount = 1 0026 baseUrl = NSURL.init(string: "https://search.mapzen.com")! // Force the unwrap because we must have a base URL to operate 0027 } 0028 0029 public func performSearch(config: PeliasSearchConfig) -> PeliasOperation { 0030 return executeOperation(config); 0031 } 0032 0033 public func reverseGeocode(config: PeliasReverseConfig) -> PeliasOperation { 0034 return executeOperation(config); 0035 } 0036 0037 public func autocompleteQuery(config: PeliasAutocompleteConfig) -> PeliasOperation { 0038 0039 return executeAutocompleteOperation(config) 0040 } 0041 0042 public func placeQuery(config: PeliasPlaceConfig) -> PeliasOperation { 0043 return executeOperation(config) 0044 } 0045 0046 public func cancelOperations() { 0047 self.operationQueue.cancelAllOperations() 0048 self.autocompleteOperationQueue.cancelAllOperations() 0049 } 0050 0051 private func executeOperation
PeliasSearchManager.swift:14 static let sharedInstance = PeliasSearchManager()(config: APIConfigData) -> PeliasOperation { 0052 //Build a operation 0053 let searchOp = PeliasOperation(config: config) 0054 0055 //Enqueue search object so it can begin processing 0056 operationQueue.addOperation(searchOp) 0057 0058 return searchOp; 0059 } 0060 0061 private func executeAutocompleteOperation
PeliasSearchManager.swift:30 return executeOperation(config);PeliasSearchManager.swift:34 return executeOperation(config);PeliasSearchManager.swift:43 return executeOperation(config)PeliasSearchManager.swift:65 return executeOperation(config)(config: PeliasAutocompleteConfig) -> PeliasOperation { 0062 //Rate Limiter 0063 //First we check to see if we have a delay stored - if not, we use the existing operation queue to immediately fire 0064 if (autocompleteTimeDelay <= 0) { 0065 return executeOperation(config) 0066 } 0067 0068 let operation = PeliasOperation(config: config) 0069 queuedAutocompleteOp = operation 0070 // We may be executing an existing operation, so lets see if we have a timer 0071 // Conceivably this could get called from multiple threads, in which case we should probably synchronize on the timer variable. We'll deal with that if it comes to that 0072 if autocompleteQueryTimer == nil { 0073 //We don't have a timer, so lets boot one up and start the engine ticking 0074 self.autocompleteTimerExecute() 0075 } 0076 0077 return operation 0078 } 0079 0080 @objc private func autocompleteTimerExecute
PeliasSearchManager.swift:39 return executeAutocompleteOperation(config)() { 0081 //Check to see if we have an operation waiting for us 0082 if let operation = queuedAutocompleteOp { 0083 //We have one! Lets fire it, and then create a new timer that will fire once in whatever delay there is from now 0084 print("Engaging Rate limiter") 0085 autocompleteOperationQueue.addOperation(operation) 0086 queuedAutocompleteOp = nil 0087 autocompleteQueryTimer = NSTimer.scheduledTimerWithTimeInterval(autocompleteTimeDelay, target: self, selector: "autocompleteTimerExecute", userInfo: nil, repeats: false) 0088 } 0089 else { 0090 //We don't have one! Set it to nil so we come back into this function 0091 autocompleteQueryTimer = nil 0092 } 0093 } 0094 } 0095 0096 public class PeliasOperation
PeliasSearchManager.swift:74 self.autocompleteTimerExecute(): NSOperation { 0097 0098 let config
PeliasSearchManager.swift:18 internal var queuedAutocompleteOp: PeliasOperation?PeliasSearchManager.swift:29 public func performSearch(config: PeliasSearchConfig) -> PeliasOperation {PeliasSearchManager.swift:33 public func reverseGeocode(config: PeliasReverseConfig) -> PeliasOperation {PeliasSearchManager.swift:37 public func autocompleteQuery(config: PeliasAutocompleteConfig) -> PeliasOperation {PeliasSearchManager.swift:42 public func placeQuery(config: PeliasPlaceConfig) -> PeliasOperation {PeliasSearchManager.swift:51 private func executeOperation(config: APIConfigData) -> PeliasOperation {PeliasSearchManager.swift:53 let searchOp = PeliasOperation(config: config)PeliasSearchManager.swift:61 private func executeAutocompleteOperation(config: PeliasAutocompleteConfig) -> PeliasOperation {PeliasSearchManager.swift:68 let operation = PeliasOperation(config: config): APIConfigData 0099 0100 init
PeliasSearchManager.swift:101 self.config = configPeliasSearchManager.swift:108 NSURLSession.sharedSession().dataTaskWithURL(config.searchUrl()) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void inPeliasSearchManager.swift:117 self.config.completionHandler(searchResponse)(config: APIConfigData) { 0101 self.config = config 0102 } 0103 0104 override public func main() { 0105 if self.cancelled { 0106 return 0107 } 0108 NSURLSession.sharedSession().dataTaskWithURL(config.searchUrl()) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in 0109 if self.cancelled { 0110 return 0111 } 0112 let searchResponse = PeliasResponse(data: data, response: response, error: error) 0113 NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in 0114 if self.cancelled { 0115 return 0116 } 0117 self.config.completionHandler(searchResponse) 0118 }) 0119 }.resume() 0120 } 0121 } 0122 0123 public class PeliasResponse
PeliasSearchManager.swift:53 let searchOp = PeliasOperation(config: config)PeliasSearchManager.swift:68 let operation = PeliasOperation(config: config): APIResponse { 0124 let data
ConfigProtocol.swift:76 var completionHandler: (PeliasResponse) -> Void { get set }PeliasAutocompleteConfig.swift:37 var completionHandler: (PeliasResponse) -> VoidPeliasAutocompleteConfig.swift:39 init(searchText: String, focusPoint: GeoPoint, completionHandler: (PeliasResponse) -> Void){PeliasPlaceConfig.swift:15 var completionHandler: (PeliasResponse) -> VoidPeliasPlaceConfig.swift:31 init(places: [PlaceAPIQueryItem], completionHandler: (PeliasResponse) -> Void){PeliasReverseGeoConfig.swift:24 var completionHandler: (PeliasResponse) -> VoidPeliasReverseGeoConfig.swift:66 init(point: GeoPoint, completionHandler: (PeliasResponse) -> Void){PeliasSearchConfigObject.swift:23 var completionHandler: (PeliasResponse) -> VoidPeliasSearchConfigObject.swift:97 init(searchText: String, completionHandler: (PeliasResponse) -> Void){PeliasSearchManager.swift:112 let searchResponse = PeliasResponse(data: data, response: response, error: error): NSData? 0125 let response
PeliasSearchManager.swift:130 self.data = data: NSURLResponse? 0126 let error
PeliasSearchManager.swift:131 self.response = response: NSError? 0127 var parsedResponse
PeliasSearchManager.swift:132 self.error = error: PeliasSearchResponse? 0128 0129 init
PeliasSearchManager.swift:134 parsedResponse = PeliasSearchResponse(parsedResponse: dictResponse)(data: NSData?, response: NSURLResponse?, error: NSError?) { 0130 self.data = data 0131 self.response = response 0132 self.error = error 0133 if let dictResponse = parseData(data) { 0134 parsedResponse = PeliasSearchResponse(parsedResponse: dictResponse) 0135 } 0136 } 0137 0138 private func parseData
PeliasSearchManager.swift:112 let searchResponse = PeliasResponse(data: data, response: response, error: error)(data: NSData?) -> NSDictionary? { 0139 let JSONData = data! 0140 do { 0141 let JSON = try NSJSONSerialization.JSONObjectWithData(JSONData, options:NSJSONReadingOptions(rawValue: 0)) 0142 guard let JSONDictionary :NSDictionary = JSON as? NSDictionary else { 0143 print("Not a Dictionary") 0144 // put in function 0145 return nil 0146 } 0147 print("JSONDictionary! \(JSONDictionary)") 0148 return JSONDictionary 0149 } 0150 catch let JSONError as NSError { 0151 print("\(JSONError)") 0152 } 0153 return nil 0154 } 0155 } 0156 0157 public struct PeliasSearchResponse
PeliasSearchManager.swift:133 if let dictResponse = parseData(data) {{ 0158 let parsedResponse
PeliasSearchManager.swift:127 var parsedResponse: PeliasSearchResponse?PeliasSearchManager.swift:134 parsedResponse = PeliasSearchResponse(parsedResponse: dictResponse)PeliasSearchManager.swift:164 static func encode(response: PeliasSearchResponse) {PeliasSearchManager.swift:170 static func decode() -> PeliasSearchResponse? {PeliasSearchManager.swift:177 extension PeliasSearchResponse {PeliasSearchManager.swift:182 var response: PeliasSearchResponse?PeliasSearchManager.swift:184 init(response: PeliasSearchResponse) {PeliasSearchManager.swift:198 response = PeliasSearchResponse(parsedResponse: parsedResponse): NSDictionary 0159 0160 init
PeliasSearchManager.swift:161 self.parsedResponse = parsedResponsePeliasSearchManager.swift:204 aCoder.encodeObject(response!.parsedResponse, forKey: "parsedResponse")(parsedResponse: NSDictionary) { 0161 self.parsedResponse = parsedResponse 0162 } 0163 0164 static func encode(response: PeliasSearchResponse) { 0165 let personClassObject = HelperClass(response: response) 0166 0167 NSKeyedArchiver.archiveRootObject(personClassObject, toFile: HelperClass.path()) 0168 } 0169 0170 static func decode() -> PeliasSearchResponse? { 0171 let responseClassObject = NSKeyedUnarchiver.unarchiveObjectWithFile(HelperClass.path()) as? HelperClass 0172 0173 return responseClassObject?.response 0174 } 0175 } 0176 0177 extension PeliasSearchResponse { 0178 0179 //TODO: I'm still not sure of this approach - might be better to implement something more like a proper protocol like http://redqueencoder.com/property-lists-and-user-defaults-in-swift but this works for now 0180 class HelperClass
PeliasSearchManager.swift:134 parsedResponse = PeliasSearchResponse(parsedResponse: dictResponse)PeliasSearchManager.swift:198 response = PeliasSearchResponse(parsedResponse: parsedResponse): NSObject, NSCoding { 0181 0182 var response
PeliasSearchManager.swift:165 let personClassObject = HelperClass(response: response)PeliasSearchManager.swift:167 NSKeyedArchiver.archiveRootObject(personClassObject, toFile: HelperClass.path())PeliasSearchManager.swift:171 let responseClassObject = NSKeyedUnarchiver.unarchiveObjectWithFile(HelperClass.path()) as? HelperClassPeliasSearchManager.swift:171 let responseClassObject = NSKeyedUnarchiver.unarchiveObjectWithFile(HelperClass.path()) as? HelperClass: PeliasSearchResponse? 0183 0184 init
PeliasSearchManager.swift:173 return responseClassObject?.responsePeliasSearchManager.swift:185 self.response = responsePeliasSearchManager.swift:196 guard let parsedResponse = aDecoder.decodeObjectForKey("parsedResponse") as? NSDictionary else { response = nil; super.init(); return nil }PeliasSearchManager.swift:198 response = PeliasSearchResponse(parsedResponse: parsedResponse)PeliasSearchManager.swift:204 aCoder.encodeObject(response!.parsedResponse, forKey: "parsedResponse")(response: PeliasSearchResponse) { 0185 self.response = response 0186 super.init() 0187 } 0188 0189 class func path
PeliasSearchManager.swift:165 let personClassObject = HelperClass(response: response)() -> String { 0190 let documentsPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).first 0191 let path = documentsPath?.stringByAppendingString("/Response") 0192 return path! 0193 } 0194 0195 required init?(coder aDecoder: NSCoder) { 0196 guard let parsedResponse = aDecoder.decodeObjectForKey("parsedResponse") as? NSDictionary else { response = nil; super.init(); return nil } 0197 0198 response = PeliasSearchResponse(parsedResponse: parsedResponse) 0199 0200 super.init() 0201 } 0202 0203 func encodeWithCoder(aCoder: NSCoder) { 0204 aCoder.encodeObject(response!.parsedResponse, forKey: "parsedResponse") 0205 } 0206 } 0207 }
PeliasSearchManager.swift:167 NSKeyedArchiver.archiveRootObject(personClassObject, toFile: HelperClass.path())PeliasSearchManager.swift:171 let responseClassObject = NSKeyedUnarchiver.unarchiveObjectWithFile(HelperClass.path()) as? HelperClass