How to remove an observer for NSNotification in a UIView? - iphone

I've added an observer in a custom UIView I've created under initWithFrame:.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(updateZipFromLocation:)
name:#"zipFoundFromLocation"
object:nil];
The problem is, this view is a subview. When the view is loaded again, it calls the initWithFrame message again, thus adding two observers and so on. How can I remove the observer when the view is going to disappear? Since it is a UIView, it says that viewWillDisappear:(BOOL)animated is not a valid method. Any ideas?

You've said that initWithFrame: is being called more than once, so I assume this means that the view is being destroyed and recreated. You can remove the view as an observer in dealloc, which will be called when the view is no longer retained by anyone:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}

Related

Adding an observer to each view or present view dynamically

I am posting a notification locally in the app when ever I receive a remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(#"Received notification: %#", userInfo);
[[NSNotificationCenter defaultCenter] postNotificationName:#"NEWMESSAGE" object:nil userInfo:userInfo]; }
I have added an observer to the view in the function viewWillAppear() and remove the observer in viewWillDisappear().
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(newMessageReceived:) name:#"NEWMESSAGE" object:nil];
and
[[NSNotificationCenter defaultCenter] removeObserver:self];
My question is I want to override every viewWillAppear and viewWillDisappear functions in all *.m files that use these functions in my app.
or how can I dynamically add an observer (like above) to the present view and remove the observer when that view disappears. it should be like a global action whenever view changes observer to be added and removed when it changes again.
Is this possible? if so please guide me.
thanks in advance.
Some thoughts:
You can subclass UIViewController and implement these method in the subclass-ed view controller class. Then you need to create all your views as the subclass of this UIViewController.
Example:
//Creating a custom subclass of UIViewController
#interface CustomViewController : UIViewController
#end
#implementation CustomViewController
- (void)viewWillAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(newMessageReceived:) name:#"NEWMESSAGE" object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#end
And create all your view controller as the subclass of CustomViewController.

NSNotificationCenter postNotificationName exec_badaccess

I have a view controller, when it's dissming with completion, I post a notfication, and in a subview which contained in another view controller, has added as a oberserve. But, when it tries to execute post notificaiton methode, exec_bad_access happend. what's wrong? The codes are:
BrandListByIdViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *bid = self.brands[indexPath.row][#"id"];
[self dismissViewControllerAnimated:YES completion:^{
[[NSNotificationCenter defaultCenter] postNotificationName:#"SelectedBrandId" object:nil];
}];
}
SearchNewProduct.h
#interface SearchNewProduct : UIView
#end
SearchNewProduct.m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didSelectedBrandId::) name:#"SelectedBrandId" object:nil];
}
}
- (void)didSelectedBrandId:(NSNotification *)notif{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
Even I get rid of the userInfo, still bad access. I created a similar situation in another new project, it works fine.
I didn't realize that you were dealing with a UIView and not a UIViewController (should have read your question better). I think what is happening is that the View is receiving notifications even after being released. Make sure to call dealloc in your UIView and remove itself as an observer:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Also, put an NSLog in that UIView's initWithFrame method to see if it is being called more than once.
This question is very similar:
ios notifications to "dead" objects
Not sure if this is the reason, but when you add your view to the notification center, your selector is wrong:
selector:#selector(didSelectedBrandId::)
There should only be one colon. The entire line should be:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didSelectedBrandId:) name:#"SelectedBrandId" object:nil];
Two colons indicates the method takes two arguments, but it only takes one.

UIKeyboardDidHideNotification error application crashing

I'm using a UIView. The application is using ARC. UIView is used in multiple view controllers. In UIView a listener to the UIKeyboardDidHideNotification is added. The listener works fine with some view controllers and with other view controllers it crashes the application. Especially when I use in the second view contoller after using in the first. The error is
* -[appname keyboardWillHide]: message sent to deallocated instance 0xb9c2760
In some scenarios the listener is getting called twice.
The code i have added in the uiview drawrect method is:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide) name:UIKeyboardWillHideNotification object:nil];
the code for listener is
-(void)keyboardWillHide
{
if(boolisViewlifted)
{
CGRect newFrame=self.frame;
newFrame=CGRectMake(self.frame.origin.x, self.frame.origin.y+250, self.frame.size.width, self.frame.size.height);
self.frame=newFrame;
boolisViewlifted=false;
}
}
The uiview appears on top of the calling view controller. Please let me know what causes this error and how to solve it.
Your view is getting unloaded because of memory warnings. You need to override dealloc method & remove observer for all notifications in all views where you added observer for notifications.
//do add in all views
-(void)dealloc
{
//[super dealloc];//As you are using ARC don't call super's dealloc
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

How to resume process on applicationDidBecomeActive

So I have around 4 viewcontrollers in this iPAd App that I am testing. Before the Application becomes inactive, the TableViewController is presnet. Once I press the button on the iPhone, it will initiate
-(void)applicationWillResignActive:(UIApplication *)application
And when I start it again, I want the application to resume with the process, with the loaded table and show the 'Screen' that was available before I pressed the Button.
I can understand that
-(void)applicationDidBecomeActive:(UIApplication *)application
is involved in this event. Could you tell me how I can actually bring a particular view controller on the event of resuming the process ??
Thanks.
You can register your own UIViewControllers as observers for `UIApplicationDidBecomeActiveNotification.
In your view controllers:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
Do not forget to remove them as observers in their dealloc methods:
- (void)dealloc {
...
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
[super dealloc];
}

dismiss a modalviewcontroller when the application enters background

i need to dismiss my uiimagepicker modal viewcontroller automatically when the application enters the background.i tried to put the code to dismissmodalviewcontroller code in viewdiddissappear method,but its not being called.so i made a reference to the viewcontroller in appdelegate and tried to put it in the applicationdidenterbackgroundmethod but still it is not working.can someone point out the right way to do this
Try to add an NSNotificationCenter observer for UIApplicationDidEnterBackgroundNotification in the UIViewController that you want to dismiss. Use the selector to dismiss the modalview
- (void)viewWillAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(didEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver: self
name:UIApplicationDidEnterBackgroundNotification
object:nil];
}
- (void)didEnterBackground:(NSNotification*)note
{
[self.navigationController dismissModalViewAnimated:NO];
}
Best way to remove the modal when app is moving to background and it works fine .
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(dismissView:)
name:UIApplicationDidEnterBackgroundNotification object:nil];
}
- (void)dismissView:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Also you can remove observer like this
[[NSNotificationCenter defaultCenter] removeObserver: self
name:UIApplicationDidEnterBackgroundNotification
object:nil];
I don't think you need to go through all that.
From the docs:
If you present several modal view controllers in succession, and thus build a stack of modal view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack.
Try calling [self dismissModalViewController:NO] from the parent view controller in your implementation of - (void) viewDidUnload.
This is untested, but the docs imply that it should do the job for you.