使用完成块显示和关闭UIViewController - 没有协议和委托

use*_*184 3 iphone uiviewcontroller ios

我想VC2从一个实例中提供一个实例,VC1并将它传递给一个完成块,当VC2它自己解散时执行.传递的完成块将是对VC1实例的方法调用.

这样做的正确方法是什么?

从VC1呈现VC2通常是:

    VC2 *vc2 = [[VC2 alloc] init];
    [self presentViewController:vc2 animated:YES completion: nil];
Run Code Online (Sandbox Code Playgroud)

在VC2中

    [self dismissViewControllerAnimated:YES completion: nil];
Run Code Online (Sandbox Code Playgroud)

(ps通常我会在VC2中忽略这样的VC2 - 即调用协议中声明的VC1方法

  [self.delegate dismissVC2]; // basically meaning VC1 to dismiss VC2
Run Code Online (Sandbox Code Playgroud)

...但我猜VC2也可以解雇自己 - 不过我不确定这总是好的.

虽然在Apple文档中,他们仍然推荐授权方案 - 但是自我解雇也是如此.

你能否对此发表评论?)

我想在VC2中这样做:

    [self dismissViewControllerAnimated:YES completion: passedBlockFromVC1];
Run Code Online (Sandbox Code Playgroud)

当呈现VC2时,passedBlockFromVC1以某种方式将此传递给VC2 - 同时包含VC1方法.

这样做的正确方法是什么?

总之,我正在寻找一个从VC1呈现VC2的解决方案,当VC2被解雇时,它在完成时调用VC1方法 - 所有这些都不需要定义协议或使用委托(我发现这在某些方面非常麻烦)案例 - 但非常可靠)

这可能并推荐吗?

非常感谢!

jac*_*ash 5

这是可能的,但您必须注意保留周期.请记住,块将捕获其中引用的任何变量,包括self.如果VC1保持对VC2的强引用,那么请注意不要让该块也强烈引用VC1.如果需要__weak,在块外面引用self并使用它.

有关使用块的保留周期以及如何避免它们的更多信息,请参阅Apple文档.

最简单的方法是子类UIViewController并创建自己的方法和属性来实现这一点.

您可以声明一个属性来将块存储为实例变量,如下所示:

@property (nonatomic, copy) dispatch_block_t completionBlock;
Run Code Online (Sandbox Code Playgroud)

使用标准的libdispatch块类型.

然后定义一些设置方法:

-(void)presentViewController:(UIViewController *)viewController animated:(BOOL)animated completion:(void (^)(void))completion dismissCompletion:(dispatch_block_t)dismissCompletion{
    self.completionBlock = dismissCompletion;
    [super presentViewController:viewController animated:animated completion:completion];
}
Run Code Online (Sandbox Code Playgroud)

然后覆盖dismiss方法以调用完成块(如果有).

-(void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion{
    if (self.completionBlock && ! completion){
        [super dismissViewControllerAnimated:flag completion:self.completionBlock];
        self.completionBlock = nil;
        return;
    }
    [super dismissViewControllerAnimated:flag completion:completion];
}
Run Code Online (Sandbox Code Playgroud)