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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 07:18:04