Swift强制解包Optional值遇nil崩溃,明明打印有值如何排查
问题根因
你遇到的崩溃触发在Int64(linkFileSize)!强制解包步骤,本质是linkFileSize的字符串内容无法转换为合法的Int64数值,和变量存储、作用域没有关系,问题出在文件大小获取逻辑的返回值存在隐藏的无效字符:
- 你通过
curl -s '下载地址' | wc -c命令获取文件大小时,wc -c的默认输出会携带前导空格和末尾换行符,比如实际返回内容为10240\n,而非纯数字字符串10240。在viewDidLoad打印时空白、换行符不会被特殊标记,看起来是正常的数字,但转换整数时会直接返回nil,触发强制解包崩溃。 - 如果AppleScript执行出错,你返回的是错误描述字符串,这类内容也无法转换为整数,同样会触发崩溃。
修复方案
1. 清洗获取到的文件大小字符串
移除返回值中的空白、换行等不可见字符,在viewDidLoad的赋值阶段做预处理:
linkFileSize = runAppleScriptString(aString: fileSizeString) .trimmingCharacters(in: .whitespacesAndNewlines)
2. 替换强制解包为安全的可选绑定
避免因转换失败直接崩溃,同时可以降级使用系统回调返回的总大小参数计算进度:
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { // 优先用自行获取的文件大小计算,失败则降级用系统返回值 let totalSize: Int64 if let customSize = Int64(linkFileSize), customSize > 0 { totalSize = customSize } else { totalSize = totalBytesExpectedToWrite } guard totalSize > 0 else { return } let percentage = CGFloat(totalBytesWritten) / CGFloat(totalSize) DispatchQueue.main.async { print("\(Int(percentage * 100))%") } }
3. 额外优化建议
你不需要单独调用curl获取文件大小,系统回调的totalBytesExpectedToWrite本身就是服务器返回的文件总大小,只要下载接口返回了正确的Content-Length响应头就可以直接使用,省略AppleScript调用步骤还能减少额外的网络请求和脚本执行的不稳定问题。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

