swift - NSNotification 观察者不会被删除,除非它被触发一次
问题描述
总之
如果用户在 VC1 上拍摄带有叠加层的照片,则会触发通知。当我展示 VC2 时,相应的观察者会被我的方法删除。
如果用户没有在 VC1 上拍照,则不会触发通知观察者。相同的移除方法称为 VC2,但观察者保持活动状态并导致 VC2 照片捕获时出现不良行为。
完整解释
我有一个注册表单,用户可以在其中拍摄一张可选的脸部照片。我正在使用一个简单的UIImagePickerController
并呈现“护照”样式的叠加层。
if sourceType == .camera {
imagePickerController.cameraDevice = .front
let overlay = PassportOverlayView(frame: imagePickerController.view.frame)
imagePickerController.cameraOverlayView = overlay
}
覆盖层覆盖了“重新拍摄”和“选择”按钮,UIImagePickerController
因此我观察以下内容NSNotifications
以在拍摄照片时移除覆盖层,并在用户希望重新拍摄照片时根据需要重新添加。
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidCaptureItem"), object:nil, queue:nil, using: { note in
self.imagePickerController.cameraOverlayView = nil
})
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidRejectItem"), object:nil, queue:nil, using: { note in
self.imagePickerController.cameraOverlayView = PassportOverlayView(frame: self.imagePickerController.view.frame)
})
一切都按预期工作。我在下一个UIViewController
推送到堆栈之前删除了通知。
func removeObservers(){
print("remove Observers")
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidCaptureItem"), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidRejectItem"), object: nil)
}
如果用户拍摄了一张照片并因此调用了观察者在下一张上添加了一张照片UIViewController
,这不需要叠加,则可以正常工作。
但是,如果用户没有在第一张照片上拍照UIViewController
[这对于我的应用程序来说非常好],他们会在第二张照片上遇到问题UIViewController
。
在这两个场景中,该removeObservers()
函数都被调用。“remove Observers”在这两种情况下都会打印到控制台。然而,当用户试图从一秒钟内拍照时,UIViewController
应用程序崩溃Unexpectedly found nil while implicitly unwrapping an Optional value
并指向通知self.imagePickerController.cameraOverlayView = nil
行。_UIImagePickerControllerUserDidCaptureItem
我理解错误,它试图删除一个cameraOverlayView
不存在的。我无法理解的是为什么当我相信它已经被移除时观察者仍然在那里。如果用户使用 拍摄第一张照片cameraOverlayView
并触发_UIImagePickerControllerUserDidCaptureItem
通知,则没有问题。观察者被删除,随后UIImagePickerControllers
没有同样的问题。
任何帮助将不胜感激。
解决方案
我想我知道你的问题是什么。保留周期导致观察者无法成功删除。之所以有保留周期,是因为您在设置通知的闭包中使用了对 self 的强引用。以下是您修复它的方法:
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidCaptureItem"), object:nil, queue:nil, using: { [unowned self] note in
self.imagePickerController.cameraOverlayView = nil
})
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidRejectItem"), object:nil, queue:nil, using: { [unowned self] note in
self.imagePickerController.cameraOverlayView = PassportOverlayView(frame: self.imagePickerController.view.frame)
})
同样,您不必担心删除观察者,因此请尝试在没有 removeObserver 的情况下运行您的代码,它应该可以工作。
希望这可以帮助。
推荐阅读
- vue.js - 如何模拟故事书故事中的模块?
- flutter - 颤振 | Dart - NoSuchMethodError:在 null 上调用了方法“map”
- javascript - 使用 Python 和 Javascript 在 CSV 中转换 HTML
- vim - 如何将 Mac OS X 终端设置为 VScode?
- google-cloud-automl - 设置访问 Google AutoML Vision 特定数据集的角色条件
- google-apps-script - 谷歌表格 - 发布日期和编辑它的用户名
- java - 同时拥有 JPA 和 Liquibase:如何处理它们的配置文件?
- python - 等高线图中的 Z 轴不自动缩放
- haskell - 未找到网络模块
- c - 为什么我用 c 编写的记忆代码不起作用?