0

I have a UIViewController where the user clicks a button and then they go onto another UIViewController to do some image manipulation. Once the image has been manipulated I want a NSNotification.

My problem as it stands out is that I am not receiving the NSNotification in the first UIViewController when the user finished cropping the image - (void) finishCropping... I covered all my grounds and put the notification handling method in viewDidLoad, viewWillAppear, viewWillAppear...

I dont understand why I am not receiving the notification? This should be quite straight forward

If i comment out the [[NSNotificationCenter defaultCenter] removeObserver:self]; from viewDidDisappear it works.... but theoretically speaking... if I am re setting the notification handlers, they should be called again in any of the 3 available methods?

First UIViewController & NSNotification Receiver

- (void) addNewPictureFromLibrary {
    [self.view endEditing:YES];

    imageCroppingViewController* popupController = [self.storyboard instantiateViewControllerWithIdentifier:@"imageCroppingView2"];

    [self.navigationController pushViewController:popupController animated:YES];

}
- (void) viewDidDisappear:(BOOL)animated    {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void) viewDidLoad {
    [self notifications];
}
- (void) viewWillAppear:(BOOL)animated {
    [self notifications];
}
- (void) viewDidAppear:(BOOL)animated {
     [self notifications];
}
    - (void) notifications {
    [[NSNotificationCenter defaultCenter]
         addObserver:self
         selector:@selector(imageCroppingView:)
         name:@"imageCroppingView"
         object:nil];
    }
- (void) imageCroppingView:(NSNotification *) notification {
    NSLog(@"imageCroppingView IN HERE");
}

Sender UIViewController

- (void) finishCropping {
    float zoomScale = 1.0 / [scrollView zoomScale];
    CGRect visibleRect;
    visibleRect.origin.x = scrollView.contentOffset.x * zoomScale;
    visibleRect.origin.y = scrollView.contentOffset.y * zoomScale;
    visibleRect.size.width = scrollView.bounds.size.width * zoomScale;
    visibleRect.size.height = scrollView.bounds.size.height * zoomScale;

    UIImage *cropped = imageFromView(imageView.image, &visibleRect);
    NSDictionary *dictionary = @{@"image":cropped};

    self.navigationController.navigationBar.hidden = NO;
    [self.navigationController popToRootViewControllerAnimated:TRUE];

    [[NSNotificationCenter defaultCenter]
     postNotificationName:@"imageCroppingView"
     object:nil
     userInfo:dictionary];

}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Jonathan Thurft
  • 4,087
  • 7
  • 47
  • 78

1 Answers1

0

This is because you are removing self from NSNotificationCenter in viewDidDisappear . When another view is loaded viewDidDisappear is called automatically on to your existing view controller and hence it de-regsiter itself for all the notifications because of this code in your first UIViewController -

- (void) viewDidDisappear:(BOOL)animated    {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

viewDidDisappear is the last method to be called before imageCroppingViewController is loaded and thereafter you never register.

If you want to selectively de-register for some notifications then call removeObserver with name method of NSNotificationCenter

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"NotificationNameYouDontWantToListenAnyLonger" object:nil];

Please note calling addObserver for a notification multiple time doesn't mean you registered for those many times. Object would have only one entry in notification center per notification (loosely speaking unique objects per notification name).

I hope this clarifies and take you towards solution. Let me know if any questions.

Ashok
  • 6,224
  • 2
  • 37
  • 55
  • Yes, I get that I am removing the Observer at `viewDidDisappear`. but I need to removeObserver and thats the best place to unregister them... The issue is that I am also registering the observers at `viewWillAppear` that gets called after `popToRootViewControllerAnimated` but not soon enough to get the passed NSNoficiation. – Jonathan Thurft Oct 29 '13 at 22:33
  • You can simply register the observer in `viewDidLoad` and removeObserver (de-register) in `dealloc` method of the view controller - It means the controller would listen the notification as long as it's alive (even when the view is not visible). Another option is register & de-register in `viewWillAppear` and `viewDidDisapper` respectively - It means the view controller would listen the notification only when visible (on screen). – Ashok Oct 29 '13 at 23:29
  • U have no dealloc method. – Jonathan Thurft Oct 30 '13 at 09:56
  • A class still have dealloc (even post Automatic Reference Counting introduction) but can't call dealloc on any object now. It is used typically for such cleanup work only. I recommend you read "ARC Enforces New Rules" (first 3 bullet points) at this link - https://developer.apple.com/library/mac/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html – Ashok Oct 30 '13 at 16:22