How to pick a selector inside a class for NSNotification? - ios

keyboard = [[FTKeyboardHelper alloc] init];
I have a keyboard helper class, and would like to call the method keyboardShow that is defined inside the keyboard.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboard.keyboardShow:)
name:UIKeyboardWillShowNotification
object:nil];
However I get the error message Excepted :
Any advice?

What about
[[NSNotificationCenter defaultCenter] addObserver:keyboard
selector:#selector(keyboardShow:)
name:UIKeyboardWillShowNotification
object:nil];
I'm not sure you can "." Separate the selector, it's not a key path.
But I think that would be bad design, you should probably put that code inside your helper.
In the - init and unregister in the - dealloc or use a pair of - register and - unregistermethod to control this outside of the normal life cycle of your object.
But don't forget to unregister before the helper is deallocated, if not, you will crash the next time the keyboard shows up.

Related

removeFromSuperview is not working if it is called from another class

I have one main view as shown in picture. I add 2 subviews into that and each has their own view controller.
In ipadMainViewController,
self.dTVC= [[dialoguesTableViewController alloc] initWithNibName:#"dialoguesTableViewController" bundle:nil];
[self.dTVC.view setFrame:rectFordTVC];
[self.view addSubview:self.dTVC.view];
After that, I want to remove the view of dialoguesTableViewController if I press a button in CategoriesViewController. But, I can't remove it.
In CategoriesViewController, I write like this but dialoguesTableViewController can't be removed from ipadMainViewController. How shall I do this?
In CategoriesViewController, I write code like this but it is not working.
self.dTVC= [[dialoguesTableViewController alloc] initWithNibName:#"dialoguesTableViewController" bundle:nil];
[self.dTVC.view removeFromSuperview];
So there are few ways how to do it:
First way:
Add observer to ipadMainViewController initialization method or viewDidLoad method it depends on your needs.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(buttonPressed)
name:#"kNotificationDidPressedButon"
object:nil];
Add -buttonPressed method to ipadMainViewController controller for removing your view or other your purposes.
- (void)buttonPressed
{
// remove view here
}
in the CategoriesViewController in the method where you tap on the appropriate button add this code:
[NSNotificationCenter defaultCenter] postNotificationName:#"kNotificationDidPressedButon"
object:self];
Second way:
Add delegate property to CategoriesViewController. you can find info how to make delegate for example here: link
Third way:
Use objective-c blocks
Initial advice as for beginner:
I suggest you to start from first way, because it is most simplest for understanding. Also you have to remove observer in ipadMainViewControllerr in -dealloc or -viewWillDisapper method, it depends of where you have add observer e.g. in -init method or in -viewDidLoad or -viewWillAppear callback;
[[NSNotificationCenter defaultCenter] removeObserver:self];
try this....
add below code where you can remove view
-(void)viewDidLoad{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(removeFromSuperview) name:#"REMOVE" object:nil];
}
-(void)removeFromSuperviev{
[view removeFromSuperview];
}
add below code form you need to remove
[[NSNotificationCenter defaultCenter] postNotificationName:#"REMOVE" object:nil];

How do I call multiple methods in #selector for notification?

Currently I'm only calling one method when application will enter foreground. How do I call various methods in #selector?
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(displayHappyFace)
name:UIApplicationWillEnterForegroundNotification
object:nil];
Just create a separate function for all your other function.
[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(AllFunction)
name:UIApplicationWillEnterForegroundNotification
object:nil];
All functions.
-(void) AllFunction
{
[self displayHappyFace];
[self otherFunction];
}
Add another observer to UIApplicationWillEnterForegroundNotification if you wish to keep the methods' logic separate:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(displayHappyFace)
name:UIApplicationWillEnterForegroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(callOtherMethod)
name:UIApplicationWillEnterForegroundNotification
object:nil];
#selector supports only one method. Remember to remove self as the observer before releasing its memory, to avoid messages being passed to a nil object.
You can only put one selector there.
Best practice is to create a new method called handleNotificationName: for each notification.
Example:
- (void)handleUIApplicationWillEnterForegroundNotification:(NSNotification *)aUIApplicationWillEnterForegroundNotification { }
This makes it really easy to figure out where your app handles each notification and makes code maintenance easy.
Inside the handler method you can call whatever methods you need to. You can have conditional logic also based on state you have or based the userInfo dictionary of the Notification ( if it has one ).
Don't forget to remove your notification observer in you object's dealloc method (at least, if not somewhere else because you might not want to always receive the notification depending on the use case)

Observer never gets removed from NSNotificationCenter

I'm adding a view controller as an observer for UIKeyboardWillShowNotification notification.
I have this code in my viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
And in my dealloc:
[[NSNotificationCenter defaultCenter] removeObserver:self];
The observer is not being removed even though dealloc is called when the view controller is closed. So when I open it for the second time, NSNotificationCenter will attempt to notify the old object, which is released, and the app crashes.
I have seen several questions here on StackOverflow about this particular problem, but non of the answers works for me.
I've tried removing the observer in viewWillDisappear and viewDidDisappear but the same problem happens.
I'm using ARC.
Have you tried this exact chunk of code in viewWillDisappear?
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
From your explanation I don't think the problem is with the removal of the observer.
Try to trigger the Observer from another viewcontroller. If it's not triggered you'll know the removal is successful and the problem occurs when you are adding the observer the second time.
Maybe try by specifying the parameter name that you have set before like this :
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
Looks like the observer is getting set multiple times. Is your controller inherited from a class which also registers for same notification? That could lead to controller instance getting registered as observer more than once. As a workaround try this, in your controller class where you add the observer,
// Remove as observer first
[[NSNotificationCenter defaultCenter] removeObserver:self];
name:UIKeyboardWillShowNotification
object:nil];
// Then add
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
This will ensure that the observer is getting added only once.
Hope that helps!
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"name" object:nil];
it works fine with me

NSNotificationCenter can lead to bugs. Do you know more elegant solutions?

I can add observer twice (by accident) to the notification center and I will get notifications twice.
Is it possible to get only one notification? Do you know more elegant solutions?
I show you this example because this may lead to bugs.
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:nil];
}
- (void)keyboardDidShow:(NSNotification *)ntf
{
}
If you're not sure if you added the observer somewhere else, you can use the following code everytime you're adding an Observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:aName object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:aSelector name:aName object:nil];
This way you are removing the old one (if it existed) and adding a new one.
It's not 100% fail proof but it's a start. This could fail in Multi-Threaded apps where the calls are being made async or other unique situations.
You can also set an object to nil and then later use that object as if was still valid.
Not everything can be made fail safe.

NSNotificationCenter addObserver not responding

In my app (game) I'm trying to use the NSNotificationCenter to pause and resume the game when either the center/home or lock button is pressed. This is the code I'm using:
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(pauseLayer:)
name:UIApplicationWillResignActiveNotification
object:self.view.layer.sublayers];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(pauseLayer:)
name:UIApplicationDidEnterBackgroundNotification
object:self.view.layer.sublayers];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(resumeLayer:)
name:UIApplicationWillEnterForegroundNotification
object:self.view.layer.sublayers];
I have experimented with putting it in lots of different places like viewDidLoad, viewDidAppear, initWithNibNameOrNil, but although they are all being called, the methods pauseLayer and resumeLayer never get called, even though the app delegate method does. Why doesn't this code work?
change the addObserver calls and remove self.view.layer.sublayers from the object param. change it to nil.
EDIT: more info
Sure. The object param tells NSNotificationCenter which object's notification you want to observe. When you specify self.view.layer.sublayers you are observing UIApplicationWillEnterForegroundNotification et al only sent by the sublayers array. Of course, the sublayers array does not send this notification. When you specify object:nil you are observing the notification from any object. That is appropriate in this case. If you want to specify an object it would be [UIApplication sharedApplication].

Resources