问题
I am using the following NSNotifications within a UIView so that the view can be notified when a UIKeyboard appears and adjust its position (frame) on screen:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
The two notifications above are being subscribed to within the -init
method of the UIView. Where is the best place to unsubscribe from these notifications once the view has disappeared off-screen? At the moment the app is crashing whenever the UIKeyboard appears in another view, presumably because a notification is still being sent to the then released UIView.
Also, is there a better place to be subscribing to the notifications, apart from within the -init
method?
Thanks for any assistance.
回答1:
-[UIView willMoveToWindow:]
and -[UIView didMoveToWindow]
are called even when a view is removed from a window. The window argument (or the window property in the case of -didMoveToWindow
) will be nil in that case, i. e.:
- (void)willMoveToWindow:(UIWindow *)newWindow {
if (newWindow == nil) {
// Will be removed from window, similar to -viewDidUnload.
// Unsubscribe from any notifications here.
}
}
- (void)didMoveToWindow {
if (self.window) {
// Added to a window, similar to -viewDidLoad.
// Subscribe to notifications here.
}
}
Except for a few edge cases this is a safe way to do it. If you need more control, you can observe the hidden property of the window to which your view belong.
回答2:
I put my removeObserver
: calls in -dealloc
.
Haven't had any problems so far.
回答3:
The definitive answer (e.g. ensure that an object is no longer reference by NSNotificationCenter
when its lifecycle ends) is to do as @Tom suggests and remove itself as an observer in dealloc
.
The subjective answer is it is also good practice to stop observing whenever the notifications are no longer relevant to the object. This is completely up to you to decide based on the design of your app. For example, if you have views that stay alive but come in and out of view you may decide to start observing when they are added to a subview and stop observing when they are removed.
WRT where the notification logic should reside (in a view vs in a controller), that's also up to you, obviously it can work both ways. I would make the decision based on the circumstances. If handling the notification in the view requires pushing app logic into the view (i.e. treating the view like a controller) then that's a red flag.
回答4:
First, you should consider when you want to stop receiving notifications:
- When view is deallocated
- When view is disappeared
You should always check if your view observes notifications and call -removeObserver:
in -dealloc
. In addition if you consider 2, override -viewWillDisappear
or -viewDidDisappear
or any other point where you manipulate view hierarchy of view's UIViewController.
I recommend you to put the logic into UIViewController because in terms of relationships UIView doesn't own its frame.
回答5:
You can create a seperate function for adding and removing observes and then later you can all those functions from the view's instance. By the way for your question's answer I would have remove the observers before removing the view itself from superview. I hope you understand.
回答6:
To unsubscribe you can use
- (void)removeObserver:(id)notificationObserver
or
- (void)removeObserver:(id)notificationObserver name:(NSString *)notificationName object:(id)notificationSender
Both methods are NSNotificationCenter
's instance methods.
Take a look at NSNotificationCenter Class Reference
回答7:
As a practice for keyboard notifications, I normally use
addObserver
in
viewWillAppear
and
removeObserver
in
viewWillDisAppear
works great for me everytime and it ensures that no keyboard notification is passed to a view which is not on screen which keeps the app safe from crashing due to false keyboard notofications.
来源:https://stackoverflow.com/questions/8200775/when-to-unsubscribe-from-a-nsnotification-in-a-uiview