【问题标题】:Am I using this block correctly?我是否正确使用了这个块?
【发布时间】:2013-10-31 02:31:13
【问题描述】:

问题:我是否正确使用了这个块?没有泄漏或保留周期?

问题 1.5:这是好的样式还是我应该只做一个内联块?

typedef void(^completionBlock)(void);

...

-(completionBlock)completionBlock{
    return ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:kFetchNewTopicsAndReloadTableData object:nil];
    };
}

..

-(void)refresh
{
    [self dismissViewControllerAnimated:YES completion:[self completionBlock]];
}

【问题讨论】:

  • 除非重复使用块,否则我发现内联块在风格上更好。

标签: ios cocoa-touch objective-c-blocks retain-cycle


【解决方案1】:

该块没有通过引用实例变量显式或隐式引用self。所以它不会保留self。表面上保留的只是元类NSNotificationCenter,我假设是一个全局常量kFetchNewTopicsAndReloadTableData,它们都不会导致其他任何东西被保留。

因此绝对没有保留周期,因为该块不处理任何瞬态对象。

即使它确实保留了self,也没有问题。与以下内容进行比较和对比:

@implementation SomeClass
{
    block_t someHandler;
}

...
    someHandler = [^{ [self doSomething]; } copy];

这会创建一个保留循环,因为该块随后由self 保留,而self 由该块保留。您以后可能会打破循环,但只使用弱引用而不是一开始就创建循环会更安全。

至于像你这样返回块是否是不好的形式:技术上是的,因为你应该有copyd 它才能返回它。如果要在声明范围之外使用块,则应复制它们。如果它是内联的,则不需要复制它,因为那将是 dismissViewControllerAnimated:... 的责任。该块将侥幸成功,因为除了全局状态之外不捕获任何内容,但这也意味着副本基本上是免费的,因此不值得例外。

至于您更可能问的问题,可以说添加一个包装块声明的额外方法会使语法过于复杂,但如果您需要多次使用相同的块,则将适用正常的因式分解规则。

【讨论】:

  • 我想补充一点,在返回之前复制一个块是由 ARC 自动管理的,因此,除非 MRC 到位,否则显式的 copy 调用将是多余的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-03
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多