【问题标题】:Method called when dismissing a UIViewController?关闭 UIViewController 时调用的方法?
【发布时间】:2010-03-14 22:42:36
【问题描述】:

当当前视图控制器被解除(弹出或解除模式对话框)时,是否有一般的最佳实践通知方式?我不能使用 -viewWillDisappear:,因为当另一个 viewController 被推到当前 viewController 上时,它也会被调用。

【问题讨论】:

  • 注意iOS 5提供了-isBeingDismissed方法,可以在viewWillDisappear:viewDidDisappear:内部调用。但是,如果您必须支持早期版本的 iOS,这将无济于事。
  • @KristopherJohnson 的答案现在应该被标记为正确答案,因为 iOS 4 几乎不存在。

标签: iphone cocoa-touch uiviewcontroller


【解决方案1】:
- (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];
}

【讨论】:

  • 请记住,如果控制器由于其父母之一被解雇而被“解雇”,这可能无法按预期工作。在这种情况下,parentViewController 不会被取消设置,但对话框仍然不可见。确实,应该更好地定义“解雇”。
【解决方案2】:

Apple 更改了演示文稿在 iOS8 中的工作方式,他们使用的是presentationControllers,因为presentationControllers 不是KVO 兼容的,我不得不使用containerView,因为它是removedFromSuperview,并且在调用-[UIPresentationController transitionDidFinish:] 时被取消。 iOS8及以上解决方案:

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

我添加观察者是 completionHandler 因为演示有时会失败,尤其是在已经演示的 viewController 上演示时。

在观察者值中,当 containerView 不再存在时,我必须删除观察:

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")
    }
}

【讨论】:

    【解决方案3】:

    据我所知,没有自动获得通知的方法,但由于 UIViewController 有一个 modalViewController 属性,您可以定义一个类似“didDismiss...”,并在呈现您的新模式后在前一个模式视图控制器上调用该方法模态视图控制器。

    【讨论】:

    • 当然,但这对标准的非模态控制器没有任何作用,而且它很脆弱(它需要父级调用它)。我知道有办法解决这个问题,我只是好奇是否有公认的“最好的方法”。
    【解决方案4】:

    你能澄清你的问题吗?

    我想你在问:

    ViewcontrollerONE 以模态方式弹出 ViewControllerTWO。 ViewControllerTWO 被解雇。 ViewControllerONE 想知道那个 ViewControllerTWO 刚刚解除了自己,并因此想运行 XYZ 方法。

    我没有好的答案,但我有办法:

    VC1 只是在 VC2 中引用。所以 VC2 可以在解雇前通知 VC1。

    【讨论】:

    • 不,ViewControllerTWO 想知道 IT 已被解雇。
    【解决方案5】:

    使用 KVO 选择的答案在 iOS 8 上对我不起作用。

    我将 UIViewController 子类化如下,然后我只在呈现的视图控制器上调用 dismissAnimated:completion: 而不是 dismissViewControllerAnimated:completion:。我注册以在其他地方观察通知并根据需要触发处理。

    #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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-01
      • 2018-01-08
      • 1970-01-01
      • 2013-04-28
      • 1970-01-01
      • 2018-08-04
      相关资源
      最近更新 更多