面试题答案
一键面试可能引发的内存管理问题
- 内存泄漏:如果在视图销毁时没有正确移除
NotificationCenter
的观察者,观察者对象(通常是视图或视图模型)会因为被NotificationCenter
强引用而无法释放,导致内存泄漏。例如,一个视图注册了接收UIKeyboardDidShow
通知,当该视图被移除屏幕并应该被销毁时,如果没有移除这个通知的观察者,该视图会一直被NotificationCenter
持有,无法被ARC回收。
避免问题的方式
- 在适当的时机移除观察者:
- 在视图销毁时移除:在SwiftUI中,可以使用
onDisappear
修饰符来移除观察者。假设视图观察UIApplication.willEnterForegroundNotification
通知:
- 在视图销毁时移除:在SwiftUI中,可以使用
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello, World!")
.onAppear {
NotificationCenter.default.addObserver(self, selector: #selector(handleEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
}
.onDisappear {
NotificationCenter.default.removeObserver(self, name: UIApplication.willEnterForegroundNotification, object: nil)
}
}
@objc func handleEnterForeground() {
// 处理通知逻辑
}
}
- **使用`NotificationCenter`的`removeObserver`方法重载**:如果有多个观察者注册在同一个对象上,可以使用`removeObserver(_:)`方法移除该对象上的所有观察者。例如:
class MyObserver {
init() {
NotificationCenter.default.addObserver(self, selector: #selector(handleNotification1), name: Notification.Name("Notification1"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleNotification2), name: Notification.Name("Notification2"), object: nil)
}
@objc func handleNotification1() {
// 处理通知1逻辑
}
@objc func handleNotification2() {
// 处理通知2逻辑
}
deinit {
NotificationCenter.default.removeObserver(self)
}
}
这样,在对象销毁时,会移除所有注册在该对象上的通知观察者,防止内存泄漏。