Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method called when dismissing a UIViewController?

Is there a general best-practices way of being notified when the current view controller is being dismissed (either popped or dismissModalDialog'd)? I can't use -viewWillDisappear:, since that also gets called when another viewController is pushed atop the current one.

like image 968
Ben Gottlieb Avatar asked Mar 14 '10 22:03

Ben Gottlieb


2 Answers

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        [self addObserver:self forKeyPath:@"parentViewController" options:0 context:NULL];
    }
    return self;
}


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([@"parentViewController" isEqualToString:keyPath] && object == self) {
        if (!self.parentViewController)
            NSLog(@"Dismissed");
    }
}

- (void)dealloc
{
    [self removeObserver:self forKeyPath:@"parentViewController"];
    [super dealloc];
}
like image 142
Jaka Jančar Avatar answered Nov 04 '22 21:11

Jaka Jančar


Apple changed how presentation is working in iOS8, they are using presentationControllers, because presentationControllers are not KVO compilant, i had to use containerView because it is removedFromSuperview and nilled when -[UIPresentationController transitionDidFinish:] is called. Solution for iOS8 and above:

self.presentationContext.presentViewController(self.viewControllerToPresent, animated: true, completion: { _ in
     self.viewControllerToPresent.presentationController?.addObserver(self, forKeyPath: "containerView", options: [], context: &self.observingContext)
})

I am adding observer is completionHandler because presentation can fail sometimes especially when presenting on already presenting viewController.

In observer value i have to remove observation when containerView no longer exists:

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    guard &self.observingContext == context else {
        super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
        return
    }
    if let presentationController = object as? UIPresentationController where presentationController.containerView == nil {
        presentationController.removeObserver(self, forKeyPath: "containerView")
    }
}
like image 21
Michal Zaborowski Avatar answered Nov 04 '22 20:11

Michal Zaborowski