使用通知的情况:
如果中间间隔多层视图,想要传递消息就使用通知(跳过多层传递)
使用通知来切换跟控制器
- 注册通知:
// 注册通知 - 如果使用 通知中心的 block 监听,其中的 self 一定要 弱引用!
//全局通知定义
let WBSwitchRootViewControllerNotification = "WBSwitchRootViewControllerNotification"
在SceneDelegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) 方法里面
// 监听通知
//控制中心 是单例
//[weak self] 控制中心 delegate 都是常驻,两个常驻最好写一个weak
// 通知名称,通知中心用来识别通知的
// 发送通知的对象,如果为nil,监听任何对象
// nil,主线程
NotificationCenter.default.addObserver(forName: NSNotification.Name.init(rawValue: WBSwitchRootViewControllerNotification), object: nil, queue: nil) { [weak self] notification in
print(Thread.current)
//通知的名称
print(notification)
//切换控制器
self?.window?.rootViewController = MainViewController()
}
在方法外面写 注销通知方法:可以不写(为了代码规范
// 注销通知 - 注销指定的通知
deinit {
NotificationCenter.default.removeObserver(self, // 监听者
name:NSNotification.Name.init(rawValue: WBSwitchRootViewControllerNotification) , // 监听的通知
object: nil) // 发送通知的对象
}
- 发送通知:
在需要调用的地方
//发送通知
NotificationCenter.default.post(name:NSNotification.Name.init(rawValue: WBSwitchRootViewControllerNotification) , object: nil)
[weak self]:
另一个例子: 在HomeTableViewController.swift里面:
NotificationCenter.default.addObserver(forName: NSNotification.Name.init(rawValue: WBStatusSelectedPhotoNotification), object: nil, queue: nil) { [weak self] (n) in
print("接收通知 \(n)")
print(self?.view ?? "")
}
-
通知中心是进程,始终和程序在一起,不会被销毁
-
通知中心是单例,始终存在,不会被销毁
-
print(self?.view ?? "") 通知对self有强引用
通知只要监听到字符串,就会执行 block,一直对self进行强引用,导致self不能被释放掉
给self发送通知,如果block里面有self,就一定会对self进行强引用,所以一般都会写[weak self]
- 加了[weak self] 之后,block里面写self就要self?
因为不知道什么时候self就被释放掉了
代码 测试循环引用问题:测试HomeTableViewController.swift是否有循环引用问题
在SceneDelegate文件中
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)里面
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let newWindow = UIWindow(windowScene: windowScene)
// 测试通知中心引用代码
let vc = UIViewController()
let nav = UINavigationController(rootViewController: vc)
vc.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "测试", style: .plain, target: self, action: #selector(self.testClick))
newWindow.rootViewController = nav
newWindow.makeKeyAndVisible()
在SceneDelegate文件中
@objc func testClick() {
// push home
let nav = window?.rootViewController as! UINavigationController
nav.pushViewController(HomeTableViewController(), animated: true)
}
设置断点:
在HomeTableViewController.swift
deinit {
// 注销通知
NotificationCenter.default.removeObserver(self)
}
开始测试:
点击测试
点击back
如果断点卡住说明成功释放: