class方法,其中self在块中使用

时间:2012-06-05 05:55:56

标签: objective-c cocoa automatic-ref-counting objective-c-blocks weak-references

我有一个使用dispatch_once创建静态对象的类方法。在dispatch_once块中,我使用[self class]并想知道是否需要使用弱引用self来避免保留周期?

+ (NSArray *)accountNames{
    static NSArray *names = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        names = [[[self class] accounts] allKeys];
        names = [names sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
    });
    return names;
}

如果我使用弱引用self,我会收到警告:

+ (NSArray *)accountNames{
    static NSArray *names = nil;
    static dispatch_once_t predicate;
    __weak TUAccount *wself = self;
    dispatch_once(&predicate, ^{
        names = [[[wself class] accounts] allKeys];
        names = [names sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
    });
    return names;
}

不兼容的指针类型使用'const Class'类型的表达式初始化'TUAccount * __ weak'

因为我收到警告,我认为在这种情况下我不需要使用弱self的引用,但我想看看你们的想法。

2 个答案:

答案 0 :(得分:11)

这里没有理由担心保留周期,因为保留或释放类对象没有意义 - 保留和释放根本没有效果。

您尝试进行弱引用是错误的,因为您正在使用类对象self并尝试将其转换为TUAccount实例。这两者完全不同。

此外,您可以简化:

names = [[[self class] accounts] allKeys];

由于self已经是一个类,[self class] == self,所以请改为:

names = [[self accounts] allKeys];

答案 1 :(得分:0)

我已经再次检查了iOS SDK Docs并找到了下一个:

  

Objective-C Objects

     

在手动引用计数环境中,复制块时会保留块中使用的局部变量。在块中使用实例变量将导致保留对象本身。如果您希望覆盖特定对象变量的此行为,可以使用__block存储类型修饰符对其进行标记。

     

如果您使用ARC,则会在复制块并稍后释放时自动保留和释放对象变量。

     
      
  • 注意:在垃圾收集环境中,如果同时将__weak和__block修饰符应用于变量,则该块将无法确保它保持活动状态。
  •   
     

如果在方法的实现中使用块,则对象实例变量的内存管理规则更加微妙:

     
      
  • 如果您通过引用访问实例变量,则保留self;
  •   
  • 如果按值访问实例变量,则保留变量。
  •   

以下示例说明了两种不同的情况:

dispatch_async(queue, ^{
    // instanceVariable is used by reference, self is retained
    doSomethingWithObject(instanceVariable);
});


id localVariable = instanceVariable;
dispatch_async(queue, ^{
    // localVariable is used by value, localVariable is retained (not self)
    doSomethingWithObject(localVariable);
});

结论:我认为在块中使用self没有问题。它将被保留并在执行后释放。

此外,您不是将块存储在内存中并直接使用它。因此它被复制到堆中,执行并从中推送。我没有看到任何保留周期。

希望我是对的!