I want to pass an object in view A to view B, that's work, but when I repeat this method, I have a crash (Thread 1: EXC_BREAKPOINT).
I initialize in my view B as :
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(hotSpotMore:) name:#"HotSpotTouched" object:nil];
}
return self;
}
- (void)hotSpotMore:(NSNotification *)notification {
self.articleVC = [[ArticlesVC alloc] init];
self.articleVC=[notification.userInfo objectForKey:#"Art"]; // ERROR LINE
}
In my View A as :
NSDictionary *myDictionary=[NSDictionary dictionaryWithObject:articles forKey:#"Art"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"HotSpotTouched" object:self userInfo:myDictionary];
I recover my object in instance variable, for the first two time, that's work and after there are a crash.
Output:
ArticlesVC setArticleVC:]: message sent to deallocated instance 0x44883f10
And in my instrument Zombie I have this eror :
An Objective-C message was sent to a deallocated 'ArticlesVC' object (zombie) at address: 0xc2d0710. 
My issue is method dealloc is called twice and I have a Zombie because my "RefCt" is set to "-1", I don't understand why this method is called twice time. How i can solve that ?
Your viewB is already dealloced, but viewA send object to viewB, which already doesn't exist. Add removeObserver into dealloc:
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Your notification observer will be added everytime you call initWithNibName for your class.
Try removing the earlier observer before adding a new one.
you can do this in either in
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
or
- (void)viewdidUnload
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Related
I am using this code to implement NSNotification listener :
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(addUserItemNotification:) name:kFinishFillUserDetails object:nil];
}
return self;
}
How i remove it:
-(void)viewDidUnload {
[super viewDidUnload];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kFinishFillUserDetails object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
And this is how i call it :
[[NSNotificationCenter defaultCenter] postNotificationName:kFinishFillUserDetails object:nil userInfo:dic];
And i have this problem:
If i create the viewcontroller and add it to UINavigationController and then remove it from the UINavigationController and then create another controller from the same type and add it to UINavigationController, And then the NSNotification called twice and not only once.
Any idea why it happen?
This is how i create the UIViewController:
UsersViewController *usersVC = [[[UsersViewController alloc]initWithNibName:#"UsersViewController" bundle:nil] autorelease];
[[self navigationController] pushViewController:usersVC animated:NO];
viewDidUnload is deprecated since iOS 6 and it's no called anymore in the view controller life cycle.
Try moving the deregistration code into dealloc.
Gabriele Petronella has the right of it. viewDidUnload is deprecated. I find the best pattern to use when registering/unregistering NSNotifications is within the viewWillAppear:animated/viewWillDisappear:animated respectively.
I have a webview I want to create a new instance of in certain situations.
I do it like this:
if(self.webViewController){
self.webViewController = nil;
[self.webViewController release];
}
self.webViewController = [[WebViewController alloc]initWithNibName:#"TheWebView" bundle:nil];
in self.webViewController I listen to a NSNotification
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
NSLog(#"INITING WebView");
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doPageRequest:) name:#"doPageRequest" object:nil];
return self;
}
However if I send a message doPageRequest, it gets invoked multiple times. So my assumption is that there are still more webView Instances "active", means: When I created the new instance, the old one is not freed correctly.
You should call the [[NSNotificationCenter defaultCenter] removeObserver:self]; in the dealloc method
Add the following, and remove the removeObserver line from your init method.
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
The self changes as you recreate a viewcontroller, it's a pointer to a new part of the memory where your new ViewController resides.
So calling [[NSNotificationCenter defaultCenter] removeObserver:self]; inside the init will never remove a previous one you added in init.
Also, you set the self.webViewController = nil; before you call release on it, obviously that won't work (you're calling release on nil), so switch the order.
[self.webViewController release];
self.webViewController = nil;
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to tell when controller has resumed from background?
How to refresh View after user enters applicationWillEnterForeground?
I want to complete recall for example HomeViewController.
I have and update function in HomeViewController and I want when user enters to call update function and reload table data.
Any class can register to UIApplicationWillEnterForegroundNotification, and react accordingly. It's not reserved to the app delegate, and helps for better separation of source code.
Create a viewDidLoad method like this for your HomeViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(yourUpdateMethodGoesHere:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
// Don't forget to remove the observer in your dealloc method.
// Otherwise it will stay retained by the [NSNotificationCenter defaultCenter]...
- (void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
If your ViewController is a tableViewController your could also directly call the reload data function:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:[self tableView]
selector:#selector(reloadData)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
- (void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
Or you could use a block:
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
[[self tableView] reloadData];
}];
You could declare a property in your app delegate class that would point to the HomeViewController object. Then you can call your update function in applicationWillEnterForeground.
I am unable to pass variables between 3 views in Objective C. I can pass data from one class to another as long as there are just 2, but if I add another view that needs to access the same delegate method, I am unable to do so.
Let me try to explain:
View1 accesses the delegate method declared in View2. However if I add another view called View3 and need to access delegate method for in View2, I cannot. I declared everything correctly and I am able to reference the delegate method, but still I cannot enter that reference in View3.
Two objects can not be both the delegate of a third. Is that your issue? If so, consider using NSNotification in order to send messages: several objects can subscribe to notifications.
if you want to passing data from 1 class to 3 classes , you had better use NSNotification.
you can use like this.
in the first receive class:
#implementation TestClass1
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (id) init
{
self = [super init];
if (!self) return nil;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveNotification1:)
name:#"TestNotification"
object:nil];
return self;
}
- (void) receiveNotification1:(NSNotification *) notification
{
NSLog(#"receive 1");
}
#end
in the 2nd receive class:
#implementation TestClass2
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (id) init
{
self = [super init];
if (!self) return nil;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveNotification2:)
name:#"TestNotification"
object:nil];
return self;
}
- (void) receiveNotification2:(NSNotification *) notification
{
NSLog(#"receive 2");
}
#end
in the 3rd receive class:
#implementation TestClass3
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (id) init
{
self = [super init];
if (!self) return nil;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveNotification3:)
name:#"TestNotification"
object:nil];
return self;
}
- (void) receiveNotification3:(NSNotification *) notification
{
NSLog(#"receive 3");
}
#end
in the post class:
- (void) yourMethod
{
[[NSNotificationCenter defaultCenter]
postNotificationName:#"TestNotification"
object:self];
}
Hi I am using NSNotificationCenter defaultCenter to implement the 'like' and 'comment' functions in my app.
//In Answer Table View
#implementation AnswerTableView
- (id)initWithParentController:(UIViewController *)pController andResourcePath:(NSString *)thisResourcePath {
....
// Notification to reload table when a comment is submitted
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reloadTable)
name:#"Comment Submitted"
object:nil];
// Notification to reload table when an answer is liked
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reloadTable)
name:#"Answer Liked"
object:nil];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
//In custom button implementation - THIS BUTTON IS CREATED IN EVERY CELL OF THE TABLEVIEW
#implementation UICustomButton
-(id)initWithButtonType:(NSString *)type {
self = [super init];
if (self) {
//Initialization done here
}
return self;
}
- (void)buttonPressed {
if ([btnType isEqualToString:#"like"]) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"Answer Liked" object:nil];
}
else if ([btnType isEqualToString:#"comment"]) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"Comment Submitted" object:nil];
}
}
However, I realize that after using these functions for a while, the response speed of the table reload gets slower and slower (to a point where it crashes).
Did I miss out anything in the implementation i.e. deallocating etc
You are repeatedly adding observers and the slowdown occurs because the notification code has to cycle over more and more observers to send notifications. You are probably crashing because you are leaking so many of these views.
Put a log statement in your dealloc to see if these instances are ever cleaned up. Also there can be timing issues with removeObserver in a dealloc method. try to remove the observer before dealloc if you can.
Sometimes its good to queue the event with Grand Central Dispatch to make sure its running on the main thread.
dispatch_async(dispatch_get_main_queue()