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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:46:58