You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 3解析Google Places JSON时CLLocationCoordinate2D坐标异常

解决Google Places iOS API解析坐标为(0.0, 0.0)的问题

嘿,我一眼就发现问题所在啦!你解析坐标的代码之所以没生效,是因为对Google Places API返回的geometry结构理解错了——它是单个字典,不是字典数组,但你把它转成了[JSONDictionary]类型,导致那段解析坐标的代码块根本没有执行,所以坐标一直是默认的CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)。

具体错误点

在你的代码中,这段判断是核心错误:

if let geometry = gym["geometry"] as? [JSONDictionary] { // 错误:geometry不是数组类型
    for result in geometry {
        if let locations = result["location"] as? [JSONDictionary] { // 同样错误:location也不是数组
            for location in locations {
                // ... 解析lat和lng的逻辑
            }
        }
    }
}

根据Google Places API的返回格式,geometry是一个包含location字段的字典,而location又是一个包含lat(浮点数)和lng(浮点数)的字典,完全不需要循环遍历数组。

修正后的完整解析代码

我不仅修正了坐标解析的问题,还优化了强制解包的风险(避免API字段缺失导致崩溃),同时补上了你遗漏的数组初始化逻辑:

func parseJsonData(data: NSData) -> [GymGooglePlace] {
    var gymGooglePlaces = [GymGooglePlace]() // 必须初始化返回数组
    do {
        typealias JSONDictionary = [String:Any]
        if let parsedData = try JSONSerialization.jsonObject(with: data as Data) as? JSONDictionary,
           let gyms = parsedData["results"] as? [JSONDictionary] {
            
            for gym in gyms {
                var coordinate = CLLocationCoordinate2D()
                
                // 正确解析geometry和location(无多余循环)
                if let geometry = gym["geometry"] as? JSONDictionary,
                   let location = geometry["location"] as? JSONDictionary,
                   let lat = location["lat"] as? CLLocationDegrees,
                   let lng = location["lng"] as? CLLocationDegrees {
                    coordinate.latitude = lat
                    coordinate.longitude = lng
                }
                
                // 优化photos解析,避免强制解包
                var maxWidth: Int?
                var photoReference: String?
                if let photos = gym["photos"] as? [JSONDictionary], let firstPhoto = photos.first {
                    maxWidth = firstPhoto["width"] as? Int
                    photoReference = firstPhoto["photo_reference"] as? String
                }
                
                // 安全拼接photoURL(避免空值崩溃)
                if let maxWidth = maxWidth, let photoReference = photoReference {
                    let photoURL = "https://maps.googleapis.com/maps/api/place/photo?maxwidth=\(maxWidth)&photoreference=\(photoReference)&key=\(googleAPIKey)"
                    print(photoURL)
                }
                
                print(coordinate)
                print("spacespacespacespacespacespacespacespacespace")
                
                // 记得创建GymGooglePlace实例并添加到返回数组
                // let gymPlace = GymGooglePlace(coordinate: coordinate, photoURL: photoURL, ...)
                // gymGooglePlaces.append(gymPlace)
            }
        }
    } catch {
        print(error)
    }
    return gymGooglePlaces
}

额外注意事项

  • 你原来的代码没有初始化gymGooglePlaces数组,也没有将解析后的对象添加进去,这会导致返回空数组,一定要补上这部分逻辑。
  • 尽量避免使用强制解包(!),一旦API返回的字段缺失或类型不匹配,App会直接崩溃,用if let的可选绑定更安全。
  • 如果photos数组为空,maxWidth和photoReference会是nil,此时不要拼接photoURL,上面的代码已经处理了这种边界情况。

内容的提问来源于stack exchange,提问作者Annabelle Sykes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:09:33