求和响应数组值时抛出异常,应用崩溃问题求助
嘿,我来帮你排查这个问题!这种情况十有八九是代理传递的数组存在未初始化/类型不匹配/为空的问题——毕竟手动测试正常,说明你的求和逻辑本身是没问题的。
先看最可能的崩溃场景(附错误代码示例)
假设你的代理相关代码是这样的:
// 代理协议定义 protocol DataPassingDelegate: AnyObject { func didReceiveData(_ data: [Int]?) } // 前一个ViewController传递数据 class PreviousVC: UIViewController { weak var delegate: DataPassingDelegate? func sendData() { // 这里可能因为异步请求未完成、数据解析失败,传了nil let data: [Int]? = nil delegate?.didReceiveData(data) } } // 当前ViewController接收数据并求和 class CurrentVC: UIViewController, DataPassingDelegate { var receivedArray: [Int] = [] func didReceiveData(_ data: [Int]?) { // 直接强制解包nil数组,必崩! receivedArray = data! sumArrayMethod1(receivedArray) } // 求和方法1:遍历累加 func sumArrayMethod1(_ array: [Int]) -> Int { var sum = 0 for num in array { sum += num } return sum } // 求和方法2:reduce简化 func sumArrayMethod2(_ array: [Int]) -> Int { return array.reduce(0, +) } }
崩溃的核心原因
- 强制解包可选值:代理传递的数组可能是
nil(比如异步请求没返回、数据解析出错),你用data!强制解包直接触发崩溃——手动测试时你传的是确定的非空数组,所以不会暴露这个问题。 - 元素类型不匹配:如果代理传递的是
[Any]类型数组(比如OC转Swift的场景),里面混了String或其他非数字类型,求和时会因为类型转换失败崩溃。 - 回调时机过早:代理在数组还没被正确初始化时就回调了(比如网络请求还没完成就调用了
didReceiveData),导致拿到空数组之外的无效数据。
针对性解决办法
办法1:安全处理可选数组,杜绝强制解包
修改回调逻辑,先做非空校验再赋值:
func didReceiveData(_ data: [Int]?) { // 先判断数组是否有效,无效则给默认空数组并提示 guard let validData = data, !validData.isEmpty else { print("代理传递的数组为空或未初始化") receivedArray = [] return } receivedArray = validData // 现在调用求和方法绝对安全 let sum1 = sumArrayMethod1(receivedArray) let sum2 = sumArrayMethod2(receivedArray) print("求和结果:方法1=\(sum1),方法2=\(sum2)") }
办法2:处理元素类型不匹配的情况
如果代理传递的是[Any]类型数组,先过滤出合法的数字元素:
// 修改代理协议(如果原协议是传递[Any]的话) protocol DataPassingDelegate: AnyObject { func didReceiveData(_ data: [Any]?) } // 在回调中做类型校验 func didReceiveData(_ data: [Any]?) { guard let rawData = data else { receivedArray = [] return } // 只保留Int类型的元素,自动过滤无效类型 let validData = rawData.compactMap { $0 as? Int } if validData.count != rawData.count { print("数组中存在非数字元素,已自动过滤") } receivedArray = validData let sum = receivedArray.reduce(0, +) print("安全求和结果:\(sum)") }
办法3:确保代理回调时机正确
在数据完全准备好后再触发代理回调(比如网络请求完成后):
// 前一个ViewController中,异步请求完成后再回调 func fetchDataFromNetwork() { // 模拟网络请求 DispatchQueue.global().asyncAfter(deadline: .now() + 1) { let fetchedData = [1,2,3,4,5] // 确保是已解析完成的有效数组 DispatchQueue.main.async { self.delegate?.didReceiveData(fetchedData) } } }
总结
核心原则就是不要盲目信任代理传递的参数,手动测试时你能控制数据的有效性,但代理传递的可能因为异步逻辑、数据错误等出现异常,必须提前做安全校验。
内容的提问来源于stack exchange,提问作者Fido
相关产品推荐
相关产品推荐

