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

Swift中Thread 1 signal SIGABRT循环崩溃问题求助

解决Swift中Thread 1: signal SIGABRT循环崩溃问题

首先,咱们来拆解一下你遇到的问题:崩溃发生在第二次触发if条件时,定位在获取openOrderMutArray[j]的FIPS值那一行。结合代码来看,核心问题出在遍历可变数组的同时直接修改原数组,以及一些不安全的类型转换操作上。

崩溃的主要原因

  1. 遍历与修改可变数组的冲突:
    你在遍历openOrderMutArray的同时,执行了openOrderMutArray.removeObject(at: j)和logOrderMutArray.add(openOrderMutArray[j])操作。虽然你手动调整了j -= 1,但logOrderMutArray是外层循环的遍历数组,往里面添加元素会导致外层循环的count动态变化,可能引发后续遍历的索引混乱。更关键的是,当openOrderMutArray元素被移除后,后续的j可能会超出数组当前的有效索引范围,触发越界崩溃。

  2. 不安全的强制类型转换:
    代码里多次使用as! NSDictionary这种强制解包操作,如果数组中存在非NSDictionary类型的元素,或者转换失败,会直接触发崩溃。另外,KVC调用value(forKey:)本身就不够安全,若对象没有对应的key,返回nil后虽然你做了默认值处理,但如果对象本身已经被释放,也会导致SIGABRT。

修复方案

方案1:改用Swift原生集合类型,避免NSMutableArray/NSDictionary

Swift的原生Array和Dictionary类型更安全,支持类型推断,能减少很多运行时错误。咱们把代码重构一下:

假设你的数组元素是[String: Any]类型,重构后的代码大概是这样:

func removeDuplicatesFromOrderAndOpenOrder() {
    var storedArray = [[String: Any]]()
    // 先复制一份openOrder数组,避免遍历原数组时修改导致的问题
    var openOrders = openOrderMutArray as! [[String: Any]]
    var logOrders = logOrderMutArray as! [[String: Any]]
    
    for i in 1..<logOrders.count { // 直接跳过i=0,不用continue
        let orderFips = logOrders[i]["FIPS"] as? NSNumber ?? 0
        let orderAccountNumber = logOrders[i]["AccountNumber"] as? String ?? ""
        
        // 倒序遍历openOrders,避免移除元素后索引混乱
        for j in (0..<openOrders.count).reversed() {
            let fips = openOrders[j]["FIPS"] as? NSNumber ?? 0
            let accountNumber = openOrders[j]["AccountNumber"] as? String ?? ""
            
            if orderFips == fips && orderAccountNumber == accountNumber {
                var editDict = logOrders[i]
                let newDict = openOrders[j]
                editDict["Inspectionlist"] = [newDict]
                logOrders[i] = editDict
                openOrders.remove(at: j)
            } else {
                storedArray.append(openOrders[j])
                logOrders.append(openOrders[j])
            }
        }
    }
    
    // 最后把修改后的数组赋值回原有的NSMutableArray
    logOrderMutArray = NSMutableArray(array: logOrders)
    openOrderMutArray = NSMutableArray(array: openOrders)
}

方案2:如果必须使用NSMutableArray,避免遍历原数组

如果你因为历史原因必须保留NSMutableArray,那要遍历数组的副本,而不是原数组:

func removeDuplicatesFromOrderAndOpenOrder() {
    let storedArray = NSMutableArray()
    // 复制一份openOrder的副本用于遍历
    let openOrderCopy = openOrderMutArray.mutableCopy() as! NSMutableArray
    
    for i in 0..<logOrderMutArray.count {
        if i == 0 { continue }
        
        let orderItem = logOrderMutArray[i] as! NSDictionary
        let orderFipsValue = orderItem.value(forKey: "FIPS") as? NSNumber ?? 0
        let orderAccountNumberValue = orderItem.value(forKey: "AccountNumber") as? String ?? ""
        
        for j in (0..<openOrderCopy.count).reversed() {
            let openItem = openOrderCopy[j] as! NSDictionary
            let fipsValue = openItem.value(forKey: "FIPS") as? NSNumber ?? 0
            let accountNumberValue = openItem.value(forKey: "AccountNumber") as? String ?? ""
            
            if orderFipsValue == fipsValue && orderAccountNumberValue == accountNumberValue {
                let editDict = orderItem.mutableCopy() as! NSMutableDictionary
                let newMutableArray = NSMutableArray(object: openItem)
                editDict.setValue(newMutableArray, forKey: "Inspectionlist")
                logOrderMutArray.replaceObject(at: i, with: editDict)
                openOrderMutArray.removeObject(at: j)
                openOrderCopy.removeObject(at: j)
            } else {
                storedArray.add(openItem)
                logOrderMutArray.add(openItem)
            }
        }
    }
}

关键优化点

  • 倒序遍历数组:当需要移除元素时,倒序遍历可以避免因为数组长度变化导致的索引偏移问题,不用手动调整j的值。
  • 使用数组副本遍历:避免修改原数组时影响遍历的索引范围,从根源上防止数组越界。
  • 减少强制解包:尽量用as?代替as!,如果必须强制解包,确保该元素一定是对应的类型,或者添加前置判断。

内容的提问来源于stack exchange,提问作者B.Saravana Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:24:51