Objective-C,ARC:使用__weak参数是否正确?

i_a*_*oom 0 arguments weak-references objective-c automatic-ref-counting

这是使用弱参数的一个小例子:

@interface MYTestObject : NSObject

@end

@implementation MYTestObject {
   void(^_block)(void);
}

- (void)dealloc {
   NSLog(@"DEALLOC!");
}

- (id)init {
   if (self = [super init]) {
      [self doSomethingWithObject:self];
   }
   return self;
}

- (void)doSomethingWithObject:(id __weak /* <- weak argument! */)obj {
   _block = ^{
      NSLog(@"%p", obj);
   };
}

@end
Run Code Online (Sandbox Code Playgroud)

它有效:-dealloc被称为!此外,如果你删除__weak你将获得一个保留周期,这是绝对正确的.

不知道,如果这只是一个副作用,使用弱论点是完全不安全的吗?或者它是一个特定的行为,我只是一个糟糕的谷歌用户?

Rob*_*Rob 5

两点意见:

  1. 我倾向于在其中进行局部__weak引用doSomethingWithObject,而不是将其__weak作为一个参数,如捕获时避免强引用循环self所示.

    我不认为,正如你所说的那样,"使用弱论点完全不安全".但是,如果没有别的,那么拥有一个局部__weak变量是更常见的模式,并且让我觉得它更适合作为doSomethingWithObject方法的公共接口的实现细节,而不是部分方法的公共接口.

  2. 我还block使用copy内存限定符创建一个属性.正如文档所说

    您应该指定copy为属性属性,因为需要复制块以跟踪其在原始范围之外的捕获状态.在使用自动引用计数时,您不必担心这一点,因为它会自动发生,但属性属性的最佳做法是显示结果行为.

从而:

@interface MYTestObject : NSObject
@property (nonatomic, copy) void(^block)(void);
@end

@implementation MYTestObject

- (void)dealloc {
    NSLog(@"DEALLOC!");
}

- (id)init {
    if (self = [super init]) {
        [self doSomethingWithObject:self];
    }
    return self;
}

- (void)doSomethingWithObject:(MYTestObject *)obj { 

    typeof(obj) __weak weakObj = obj;

    self.block = ^{
        NSLog(@"%p", weakObj);
    };
}

@end
Run Code Online (Sandbox Code Playgroud)