问题描述
在我的一个应用程序中,我需要对地址字符串进行地理编码。起初,我考虑使用 CLGeocoder 。然而,在我尝试之后,我偶然发现了一个我在问题。
解决方案是使用Google的Geocoding API。我已经切换到他们,并设法通过具有以下功能让他们工作:
func startConnection(){
self.data = NSMutableData()
let urlString =https://maps.googleapis.com/maps/api/geocode/json?address=\(searchBar.text!)&key=MYKEY
let linkUrl:NSURL = NSURL(string:urlString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!)!
let request:NSURLRequest = NSURLRequest(URL:linkUrl)
let connection:NSURLConnection = NSURLConnection(request:request,delegate:self,startImmediately:false)!
connection.start()
}
func连接(连接:NSURLConnection !, didReceiveData数据:NSData!){
self.data.appendData(data)
func connectionDidFinishLoading(connection:NSURLConnection!){
do {
如果让json = try NSJSONSerialization.JSONObjectWithData(data,options:NSJSONReadingOptions.MutableContainers)as? [String:AnyObject] {
print(json)
}
}
catch {
print(error1)
}
}
这很好用,解决了我用 CLGeocoder 。但是,除了提取位置坐标之外,我还需要使用Google的Timezone API为每个位置提取时区。
使用 NSURLConnection 或 NSURLSession 在我看来有点困难,因为我需要跟踪哪个会话/连接返回。所以,我想有一些使用完成处理程序的解决方案。
我试过使用Alamofire框架(使用Swift 2.0的正确分支)。但是,在这种情况下,似乎使用 request()函数是错误的。我曾尝试过:
let parameters = [address:searchBar.text!,key:MYKEY]
Alamofire.request(.GET,https://maps.googleapis.com/maps/api/geocode/json,参数:parameters).responseJSON(options:.AllowFragments){_,_,JSON in
print(JSON)
}
我印的是SUCCESS 。我希望我做错了什么,它可以被修复,因为我真的希望能够使用闭包,而不是委托调用。
我的问题是: p>
- 是否可以将Alamofire与Google Geocoding API一起使用?
- 如果有,请告诉我我做错了什么?
- 如果这是不可能的,你可以建议我如何设计一个带有 NSURSession s的系统,或者 NSURLConnection s允许我为每个调用使用完成处理程序而不是代理?
PS我知道我可以使用同步请求,但我真的想避免使用该选项。
更新
有人建议添加 .MutableContainers 作为选项应该使 responseJSON 工作。我尝试了以下代码:
let apiKey =MYKEY
var parameters = [key:apiKey, 组件:locality:\(searchBar.text!)]
Alamofire.request(.GET,https://maps.googleapis.com/maps/api/geocode/json,参数:参数).responseJSON(options:.MutableContainers){one,two,JSON in
print(JSON)
}
我打印的所有内容都是SUCCESS。
好的,我终于想通了这一点(在@cnoon的帮助下)。返回的值是 Result 类型。我找不到它的文档,但源代码可用。
为了检索JSON,可以使用下面的实现:
Alamofire.request(.GET,https://mapss.googleapis.com/maps/api/geocode/json,parameters:parameters).responseJSON(options:.MutableContainers){_,_, JSON in
switch JSON {
case .Failure(_,let error):
self.error =错误
break
case 。成功(让价值):
print(value)
break
}
}
打印的值是地理编码API响应的正确表示形式。
In one of my apps I need to geocode address string. At first I considered using CLGeocoder. However, after I tried it I stumbled upon a problem which I described in this question.
The solution was to use Google's Geocoding APIs instead. I have now switched to them and managed to get them working by having the following functions:
func startConnection(){ self.data = NSMutableData() let urlString = "https://maps.googleapis.com/maps/api/geocode/json?address=\(searchBar.text!)&key=MYKEY" let linkUrl:NSURL = NSURL(string:urlString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!)! let request: NSURLRequest = NSURLRequest(URL: linkUrl) let connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)! connection.start() } func connection(connection: NSURLConnection!, didReceiveData data: NSData!){ self.data.appendData(data) } func connectionDidFinishLoading(connection: NSURLConnection!) { do { if let json = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? [String: AnyObject] { print(json) } } catch { print("error1") } }
This works great and resolves the problem which I had with CLGeocoder. However, in addition to extracting the coordinates of place, I need to also use Google's Timezone APIs to extract the timezone for each place.
Doing this with the NSURLConnection or NSURLSession seems to me a bit difficult as I would need to keep track of which session/connection returns. So, I would like to have some solution which uses completion handlers.
I have tried using Alamofire framework (using the correct branch for Swift 2.0). However, it seems like request() function is the wrong one to use in this case. I have tried:
let parameters = ["address":searchBar.text!,"key":"MYKEY"] Alamofire.request(.GET, "https://maps.googleapis.com/maps/api/geocode/json", parameters: parameters).responseJSON(options:.AllowFragments) { _, _, JSON in print(JSON) }
And all I am getting printed is "SUCCESS". I hope that I am doing something wrong and it can be fixed because I would really like to be able to use closures instead of delegate calls.
My questions are:
- Is it possible to use Alamofire with Google Geocoding APIs?
- If so, can you please tell me what am I doing wrong?
- If it is not possible, can you please suggest me how to design a system with NSURSessions or NSURLConnections which would allow me to use completion handlers for each call instead of delegates?
P.S. I am aware that I can use synchronous requests but I would really like to avoid using that option
Update
It was suggested that adding .MutableContainers as an option should make responseJSON work. I tried the code below:
let apiKey = "MYKEY" var parameters = ["key":apiKey,"components":"locality:\(searchBar.text!)"] Alamofire.request(.GET, "https://maps.googleapis.com/maps/api/geocode/json", parameters: parameters).responseJSON(options:.MutableContainers) { one, two, JSON in print(JSON) }
And all I get printed is "SUCCESS".
Ok, I have finally figured this out (with the help from @cnoon). The value which is returned is of type Result. I couldn't find documentation for it, but the source code is available here.
In order to retrieve JSON below implementation can be used:
Alamofire.request(.GET, "https://mapss.googleapis.com/maps/api/geocode/json", parameters: parameters).responseJSON(options:.MutableContainers) { _, _, JSON in switch JSON { case .Failure(_, let error): self.error = error break case .Success(let value): print(value) break } }
The value printed is the correct representation of response from Geocoding APIs.
这篇关于Alamofire与谷歌地理编码API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!