写 Swift 时,编译器报错红标满天飞,Xcode 卡住不动,模拟器一运行就崩溃……这些场景,你是不是也经历过?别急着重写代码,很多问题其实有固定套路可循。
类型推断出错,编译器比你还懵
比如写了这么一行:
let score = 95
let message = "分数:" + scoreXcode 直接报错:Cannot convert value of type 'Int' to expected argument type 'String'。这不是语法错,是 Swift 类型安全的体现——+ 不能拼接字符串和整数。改法很简单:
let message = "分数:\(score)"或者显式转成字符串:"分数:" + String(score)。遇到类似 Binary operator '+' cannot be applied 提示,先盯住操作数类型,用 Option+Click 点一下变量名,Xcode 就会告诉你它到底是啥类型。
可选值解包翻车,崩溃就在一瞬间
新手常写:
let user = getUser() // 返回 User?如果 getUser() 返回 nil,程序直接闪退,控制台只留一句 Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value。这不是玄学,是强制解包(!)在作祟。改成安全写法:
if let user = getUser() {
print(user.name)
} else {
print("用户未登录")
}或者用空合并操作符:let name = user?.name ?? "游客"。
IBOutlet 连线失效,界面空白还找不到原因
拖了个按钮到 Storyboard,声明了 @IBOutlet weak var loginBtn: UIButton!,也连好了线,但运行后点击没反应,甚至 loginBtn 打印出来是 nil。这时候打开 Assistant Editor,确认连线右下角有没有实心圆点;再检查 ViewController 的类是否在 Identity Inspector 里正确设为对应类名;最后看 Storyboard 中该 ViewController 的 Module 是否选对(有时会莫名变成 None)。
主线程更新 UI,异步回调里千万别忘
网络请求回来想改个 label 文字:
URLSession.shared.dataTask(with: url) { data, _, _ in
self.titleLabel.text = "加载完成" // 崩溃!
}.resume()因为回调发生在后台线程,UI 操作必须在主线程。加一层 dispatch:
URLSession.shared.dataTask(with: url) { data, _, _ in
DispatchQueue.main.async {
self.titleLabel.text = "加载完成"
}
}.resume()Xcode 控制台如果出现 Modifications to the layout engine must not be performed from a background thread,基本就是这个原因。
内存循环引用,App 越跑越卡
闭包里捕获 self 又没加 [weak self],容易让对象一直不释放。比如:
networkManager.fetchData { result in
self.updateUI(result) // self 强引用闭包,闭包又强引用 self
}改成:
networkManager.fetchData { [weak self] result in
guard let self = self else { return }
self.updateUI(result)
}真机跑一阵后内存占用持续上涨、响应变慢,就该怀疑是不是哪里漏了弱引用。