块保留命名约定的周期? [英] Blocks retain cycle from naming convention?

查看:131
本文介绍了块保留命名约定的周期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我惊讶地发现以下行为...

I am surprised to find the following behavior...

@interface Foo : NSObject

- (void)addBar:(id)aBar withCompletion:(void(^)(void))completion;

@end

@interface AwesomeClass : NSObject

@property (strong, nonatomic) Foo *foo;

- (void)doSomethingWithBar:(id)bar;

@end

@implementation AwesomeClass

- (void)doSomethingWithBar:(id)bar
{
    [self.foo addBar:bar withCompletion:^{
        NSLog(@"%@", self.foo);
    }];
}

在Xcode 4.6.1中,我在执行<$ c时收到警告$ c> -doSomethingWithBar:表示在此块中强行捕获自我可能导致保留周期。

In Xcode 4.6.1 I get a warning in the implementation of -doSomethingWithBar: that "Capturing 'self' strongly in this block is likely to lead to a retain cycle."

如果我重构方法 -addBar:withCompletion: -setupBar:withCompletion:名称 c>此警告消失。看起来我的惊喜表明我在Objective-C命名约定的知识有一个空白。

However, if I refactor the name of the method -addBar:withCompletion: to -setupBar:withCompletion: this warning goes away. It seems that my surprise by this illustrates I've got a gap in my knowledge regarding Objective-C naming conventions!

推荐答案

[self.foo someMethod:bar withCompletion:^{
    NSLog(@"%@", self.foo);
}];

通常不会创建保留周期。如果 someMethod:withCompletion:只是调用块并返回,根本没有保留周期。 ( - [NSArray enumerateObjectsUsingBlock:] 是一个示例。)

does not generally create a retain cycle. If someMethod:withCompletion: just calls the block and returns, there is no retain cycle at all. (-[NSArray enumerateObjectsUsingBlock:] is an example.)

仅当 someMethod: withCompletion:记住稍后要执行的块,有可能的保留周期。因此,clang使用启发式方法来决定是否是一个类似setter的方法,将块存储到 Foo 的属性中以便稍后执行。

Only if someMethod:withCompletion: "remembers" the block to be executed later, there is a possible retain cycle. So clang uses a heuristic to decide if it is a "setter-like" method that stores the block into a property of Foo to be executed later.

-set< Key> -add< Key> 键值编码以设置属性或向一个(多对)关系添加值,这正是clang检查的。

-set<Key> and -add<Key> are accessor patterns in Key-Value Coding to set a property or add a value to a (to-many) relationship, and that is exactly what clang checks for.

这可以在 ang源代码

/// Check for a keyword selector that starts with the word 'add' or
/// 'set'.
static bool isSetterLikeSelector(Selector sel) {
  if (sel.isUnarySelector()) return false;

  StringRef str = sel.getNameForSlot(0);
  while (!str.empty() && str.front() == '_') str = str.substr(1);
  if (str.startswith("set"))
    str = str.substr(3);
  else if (str.startswith("add")) {
    // Specially whitelist 'addOperationWithBlock:'.
    if (sel.getNumArgs() == 1 && str.startswith("addOperationWithBlock"))
      return false;
    str = str.substr(3);
  }
  else
    return false;

  if (str.empty()) return true;
  return !islower(str.front());
}

这里调用:

/// Check a message send to see if it's likely to cause a retain cycle.
void Sema::checkRetainCycles(ObjCMessageExpr *msg) {
  // Only check instance methods whose selector looks like a setter.
  if (!msg->isInstanceMessage() || !isSetterLikeSelector(msg->getSelector()))
    return;

  /*
   * rest omitted
   */

}

您的 setupBar 方法不是被视为类似setter方法,因为set不是后跟一个大写字母。

Your setupBar method is not treated as "setter-like" method because "set" is not followed by an uppercase letter.

这篇关于块保留命名约定的周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆