【问题标题】:present and dismiss UIViewController with completion blocks - without protocols and delegates使用完成块呈现和关闭 UIViewController - 没有协议和委托
【发布时间】:2012-09-21 09:49:18
【问题描述】:

我想从VC1 的实例中呈现VC2 的实例,并传递一个完成块以在VC2 自行关闭时执行。传递的完成块将是对VC1 实例的方法调用。

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

虽然从 VC1 呈现 VC2 通常是:

    VC2 *vc2 = [[VC2 alloc] init];
    [self presentViewController:vc2 animated:YES completion: nil];

在 VC2 中

    [self dismissViewControllerAnimated:YES completion: nil];

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

  [self.delegate dismissVC2]; // basically meaning VC1 to dismiss VC2

...但我猜 VC2 也可以自行解散 - 但是我不确定这总是可以的。

虽然在 Apple 文档中,他们仍然推荐委托方案 - 但是自我解雇也可以。

您也可以对此发表评论吗?)

我想在 VC2 中做这样的事情:

    [self dismissViewControllerAnimated:YES completion: passedBlockFromVC1];

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

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

总之,我正在寻找一种从 VC1 呈现 VC2 的解决方案,当 VC2 get 被解除时,它会在完成时调用 VC1 方法——所有这些都无需定义协议或使用委托(我觉得这对某些人来说很麻烦在这种情况下扩展 - 但非常可靠)

这可能并推荐吗?

非常感谢!

【问题讨论】:

    标签: iphone ios uiviewcontroller


    【解决方案1】:

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

    See the Apple Documentation for more information about retain cycles using blocks and how to avoid them.

    最简单的做法是继承 UIViewController 并创建自己的方法和属性来实现这一点。

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

    @property (nonatomic, copy) dispatch_block_t completionBlock;
    

    使用标准的 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];
    }
    

    然后重写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];
    }
    

    【讨论】:

    • 哇——这看起来很不错而且很容易做到。由于它遵循 VC2 自行解散(而不是通过委托 VC1)的方案(正如我一直在寻找的那样) - 您是否知道使用它是否比遵循 Apple 推荐的委托方式有任何缺点?这看起来更直接,更灵活,更容易编码 - 为什么 Apple 甚至不提到这样的东西作为一个有效的替代方案?
    • 可能是因为,如果您不知道自己在做什么,那么很容易获得保留周期。可能是因为委托是这里的正常模式,其他人可以更快地理解您的代码。也许是因为如果它没有坏就不要修复它?此外,VC2 可能希望根据用户输入或其他内容执行不同的完成实现。如果它对您有用并且您知道这些限制,那么如果您愿意,那就去做吧。
    • 非常感谢 - 我将开始使用它作为我的“标准” - 这避免了协议和代表的创建 - 虽然我认为它更容易阅读和理解,因为它都在一个地方。
    • 大家好,我知道它已经过时了。但你使用的方式正是我一直在寻找的东西。您能否提供更多关于我在哪里声明这些方法和属性的信息?因为我不能完全让它工作。我是在 VC1 还是 VC2 中声明它们?以及如何调用新的 presentViewController 方法?百万谢谢。
    • 一切都在 VC2 中。然后你从 VC1 调用-(void)presentViewController:(UIViewController *)viewController animated:(BOOL)animated completion:(void (^)(void))completion dismissCompletion:(dispatch_block_t)dismissCompletion。同样,要注意限制很容易使保留周期
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    • 2021-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多