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

Swift代码遇非法/空数据崩溃求助:do-catch尝试无效

解决你的Swift代码崩溃问题

我一眼就看到问题所在了——你的代码里到处都是**强制解包(!)和直接访问数组索引[0]**的操作,这些都是Swift里的“崩溃雷区”!当数据不符合预期(比如TextField.text为空、Plist文件读取失败、filter后没有匹配结果)时,这些操作会直接触发致命错误,而do{}catch{}抓不到这类错误,因为它们不是可抛出的Error类型,而是运行时的致命错误。

下面一步步帮你修复这些问题:

1. 修复getSwiftArrayFromPlist函数

这个函数里有两处强制解包:path!和(arr as? ...)!,只要Plist文件找不到或者解析失败,就会崩溃。我们改成安全的可选绑定+默认值:

func getSwiftArrayFromPlist(name: String) -> [[String: String]] {
    // 用可选绑定安全获取文件路径
    guard let path = Bundle.main.path(forResource: name, ofType: "plist") else {
        print("找不到指定的Plist文件:\(name).plist")
        return [] // 找不到就返回空数组,避免崩溃
    }
    // 安全读取并转换数组类型
    guard let arr = NSArray(contentsOfFile: path) as? [[String: String]] else {
        print("Plist文件解析失败,格式不符合预期")
        return []
    }
    return arr
}

2. 修复getDataforFuelConsumption函数

这里的崩溃点是array.filter(...)[0]——如果filter没有匹配到任何元素,数组为空,直接访问索引0就会触发Index out of range错误。我们用first来安全获取第一个元素,同时调整返回值为可选类型或者空数组:

func getDataforFuelConsumption(data: String) -> [[String: String]] {
    let array = getSwiftArrayFromPlist(name: "LongRange")
    let namePredicate = NSPredicate(format: "altitude = %@", data)
    // 过滤后获取第一个匹配元素,first返回可选值
    guard let matchedItem = array.filter({ namePredicate.evaluate(with: $0) }).first else {
        print("没有找到匹配altitude为\(data)的数据")
        return [] // 没有匹配结果返回空数组
    }
    return [matchedItem]
}

或者如果你希望返回可选类型(更明确表示可能无结果),可以改成:

func getDataforFuelConsumption(data: String) -> [[String: String]]? {
    let array = getSwiftArrayFromPlist(name: "LongRange")
    let namePredicate = NSPredicate(format: "altitude = %@", data)
    if let matchedItem = array.filter({ namePredicate.evaluate(with: $0) }).first {
        return [matchedItem]
    } else {
        print("没有找到匹配altitude为\(data)的数据")
        return nil
    }
}

3. 修复viewDidLoad里的代码

这里同样有TextField.text!的强制解包,以及直接访问[0]的问题,改成安全的可选绑定:

override func viewDidLoad() {
    super.viewDidLoad()
    let array = getSwiftArrayFromPlist(name: "LongRange")
    // 安全获取TextField的文本,为空时直接返回或者做默认处理
    guard let inputText = TextField.text, !inputText.isEmpty else {
        print("输入框为空,请输入有效数据")
        return
    }
    let namePredicate = NSPredicate(format: "altitude = %@", inputText)
    // 安全获取第一个匹配元素
    guard let matchedItem = array.filter({ namePredicate.evaluate(with: $0) }).first else {
        print("没有找到匹配altitude为\(inputText)的数据")
        return
    }
    let coordinate = "\(matchedItem)" // 这里不需要用NSString转换,直接字符串插值更简洁
}

为什么do{}catch{}没用?

因为你遇到的崩溃是Swift的致命错误(Fatal Error),比如强制解包nil、数组索引越界,这些错误会直接终止程序,不属于throws抛出的可捕获错误范畴。所以要避免这类崩溃,核心是用可选绑定、guard let、first等安全方式处理可选值和数组,而不是依赖do{}catch{}。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:11:01