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
相关产品推荐
相关产品推荐

