摘要
[如果用户在VC1上拍摄了带有叠加层的照片,则会触发通知。当我提交VC2时,我的方法删除了相应的观察者。
[如果用户未在VC1上拍照,则不会触发通知查看器。提出了与VC2相同的删除方法,但观察者保持活动状态,并且会因VC2照片捕获而导致不良行为。
完整说明
我有一个注册表,用户可以在其中注册自己的面部照片。我正在使用简单的UIImagePickerController
,并呈现“护照”样式的覆盖物。
if sourceType == .camera {
imagePickerController.cameraDevice = .front
let overlay = PassportOverlayView(frame: imagePickerController.view.frame)
imagePickerController.cameraOverlayView = overlay
}
叠加层覆盖了UIImagePickerController
的'retake'和'choose'按钮,因此我观察到以下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()
功能。两次都将“删除观察者”打印到控制台。但是,当用户尝试从第二个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的情况下运行代码,它应该可以工作。
希望这会有所帮助。
收到Reddit帖子的回复后,我已经解决了我的问题。
添加我的observers
时,我应该已经明确了,并将self
设置为对象,而不是nil
。当我第一次编写代码时,我认为nil
不会成为问题,因为我自己会删除observers
。
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidCaptureItem"), object:self, queue:nil, using: { note in
self.imagePickerController.cameraOverlayView = nil
})
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidRejectItem"), object:self, queue:nil, using: { note in
self.imagePickerController.cameraOverlayView = PassportOverlayView(frame: self.imagePickerController.view.frame)
})
上面的代码现在可以按预期工作。
将对象设置为自身时,ARC
会处理observer
,并会自动将其删除。
我最初的问题是,为什么observer
除非被使用过,否则为什么不被删除,我只能怀疑observer
一直在等待直到它被首次调用,并为object
分配了一些东西。 C0]。
不管后台发生了什么,在声明观察者时我都会更加小心和明确。