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 cal开发者_JS百科led when another viewController is pushed atop the current one.
- (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];
}
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")
}
}
As far as I know there's no automatic way to get notified, but since UIViewController has a modalViewController property, you could define a like "didDismiss...", and call that method on the previous modal view controller after presenting your new modal view controller.
Can you clarify you question?
I'm thinking that you're asking:
ViewcontrollerONE pops up ViewControllerTWO modally. ViewControllerTWO is dismissed. ViewControllerONE wants to know that That ViewControllerTWO just dismissed itself, and wants to run XYZ method because of it.
I don't have a good answer, but I do have a way:
VC1 is simply referenced in VC2. so VC2 can notify VC1 before dismissal.
The selected answer using KVO did not work for me on iOS 8.
I subclassed UIViewController as follows and then I just call dismissAnimated:completion:
on the presented view controller instead of dismissViewControllerAnimated:completion:
. I register for observing the notification elsewhere and trigger handling as needed.
#define DismissNotifyViewControllerDismissedNotification @"DismissNotifyViewControllerDismissed"
@interface DismissNotifyViewController : UIViewController
- (void)dismissAnimated:(BOOL)flag completion:(void (^)(void))completion;
@end
@implementation DismissNotifyViewController
- (void)dismissAnimated:(BOOL)flag completion:(void (^)(void))completion
{
[self.presentingViewController dismissViewControllerAnimated: flag
completion: ^{
if (completion)
completion();
[NSNotificationCenter.defaultCenter
postNotificationName: DismissNotifyViewControllerDismissedNotification
object: self];
}];
}
@end
精彩评论