Swift应用绘制路径时[NSArray0 objectAtIndex:]错误的解决
解决Swift中绘制路径时的
[NSArray0 objectAtIndex:]崩溃问题 看起来你遇到的[NSArray0 objectAtIndex:]错误,本质是你尝试访问一个空数组的第0个元素,也就是代码里的paths[0]这一行。当Google Directions API返回的routes数组虽然存在,但里面的overview_polyline没有有效的points数据,或者解析后paths变成了空数组时,就会触发这个崩溃,进而导致应用冻结。
下面我来帮你拆解问题根源,并给出具体的修复方案:
问题根源
你的代码里有几处不安全的写法,直接导致了崩溃风险:
- 强制将
pathv.value(forKey: "points")转为NSArray,但如果没有有效数据,这个数组可能为空 - 直接用
paths[0]访问元素,完全没判断数组是否为空 - 多处使用
!强制解包,一旦值为nil就会触发崩溃
修复步骤
1. 增加空数组与可选值的安全检查
在访问paths[0]之前,先判断paths是否为空,同时用可选绑定替代强制解包,彻底避免崩溃:
把这段不安全的代码:
let pathv : NSArray = routes.value(forKey: "overview_polyline") as! NSArray let paths : NSArray = pathv.value(forKey: "points") as! NSArray let newPath = GMSPath.init(fromEncodedPath: paths[0] as! String)
替换成安全版本:
// 用可选绑定+数组空判断,确保拿到有效数据再继续 if let pathv = routes.value(forKey: "overview_polyline") as? [Any], let paths = pathv.compactMap({ ($0 as? [String: Any])?["points"] as? String }), !paths.isEmpty { // 确认路径编码字符串有效后再创建GMSPath if let newPath = GMSPath(fromEncodedPath: paths[0]) { // 后续绘制polyline的代码... } else { print("无法解析路径编码字符串") } } else { print("没有获取到有效的路径数据") }
2. 完善API返回的异常处理
你已经处理了ZERO_RESULTS和NOT_FOUND,但还要补充处理routes为空的情况,比如在获取routes之后先检查是否有元素:
if let routes = resJson["routes"].rawValue as? [Any], !routes.isEmpty { // 你的现有标记绘制、路径解析代码... } else { print("没有找到可用的路线") }
3. 修复代码里的其他潜在问题
- 你的代码里重复执行了
self.polyArray.append(polyLine),会导致同一个polyline被添加两次,删掉其中一次 - 尽量用Swift原生的
Array替代NSArray,类型更安全 - 别再把字符串强制转为
NSString来取double值,用Double()转换更符合Swift风格:// 替换旧写法 // let position = CLLocationCoordinate2D(latitude:(self.riderlat as NSString).doubleValue, longitude: (self.riderlong as NSString).doubleValue) // 改用安全的可选绑定 guard let riderLat = Double(self.riderlat), let riderLon = Double(self.riderlong) else { print("无法解析乘客坐标") return } let position = CLLocationCoordinate2D(latitude: riderLat, longitude: riderLon)
完整修复后的核心代码片段
Alamofire.request(str!).responseJSON { (responseObject) -> Void in guard let responseValue = responseObject.result.value else { print("请求失败或无响应数据") return } let resJson = JSON(responseValue) guard let status = resJson["status"].rawString() else { print("无法解析响应状态") return } switch status { case "ZERO_RESULTS": print("没有找到路线结果") case "NOT_FOUND": print("起点或终点无法识别") case "OK": guard let routes = resJson["routes"].rawValue as? [Any], !routes.isEmpty else { print("没有可用的路线数据") return } // 这里保留你原有的marker创建逻辑,记得替换成安全的坐标转换方式 self.mapView.isMyLocationEnabled = true guard let riderLat = Double(self.riderlat), let riderLon = Double(self.riderlong) else { print("乘客坐标无效") return } let position = CLLocationCoordinate2D(latitude: riderLat, longitude: riderLon) let marker = GMSMarker(position: position) marker.icon = UIImage(named: "Car.png") marker.title = "Customer have selected same location as yours" marker.map = self.mapView guard let hotelLat = Double(self.hotellat), let hotelLon = Double(self.hotellong) else { print("酒店坐标无效") return } let position2 = CLLocationCoordinate2D(latitude: hotelLat, longitude: hotelLon ) let marker1 = GMSMarker(position: position2) marker1.icon = UIImage(named: "HotelPin") marker1.appearAnimation = GMSMarkerAnimation.pop marker1.map = self.mapView self.riderMarker.icon = UIImage(named:"Car.png") self.riderMarker.map = self.mapView self.getAddressFromLatLon(pdblLatitude:StaticData.singleton.rider_lat!, withLongitude:StaticData.singleton.rider_lon!) // 清理旧的polyline for polyline in self.polyArray { polyline.map = nil } self.polyArray.removeAll() // 安全解析路径数据 if let pathv = routes.compactMap({ $0 as? [String: Any] }), let overviewPolylines = pathv.compactMap({ $0["overview_polyline"] as? [String: String] }), let paths = overviewPolylines.compactMap({ $0["points"] }), !paths.isEmpty, let newPath = GMSPath(fromEncodedPath: paths[0]) { let polyLine = GMSPolyline(path: newPath) polyLine.strokeWidth = 5 polyLine.strokeColor = UIColor(red: 190/255.0, green: 44/255.0, blue: 44/255.0, alpha: 1.0) polyLine.map = self.mapView self.polyArray.append(polyLine) let bounds = GMSCoordinateBounds(path: newPath) self.mapView.animate(with: GMSCameraUpdate.fit(bounds, withPadding: 50.0)) } else { print("无法获取有效的路径编码") } default: print("API返回异常状态: \(status)") } }
这样修改后,不仅能避免空数组访问导致的崩溃,还能处理多种异常情况,让代码更健壮。
内容的提问来源于stack exchange,提问作者Aaron34
相关产品推荐
相关产品推荐

