7

我有一个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但我想看看你们的想法。

4

2 回答 2

11

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

您尝试进行弱引用是错误的,因为您正在获取一个类对象self并尝试将其强制转换为TUAccount. 两者是完全不同的东西。

此外,您可以简化:

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

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

names = [[self accounts] allKeys];
于 2012-06-05T06:29:47.893 回答
0

我又检查了一次 iOS SDK Docs 并找到了下一个:

Objective-C 对象

在手动引用计数的环境中,复制块时保留块内使用的局部变量。在块中使用实例变量将导致对象本身被保留。如果您希望为特定对象变量覆盖此行为,您可以使用 __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在块中使用没有问题。它将被保留并在执行后释放。

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

希望我是对的!

于 2012-06-05T06:24:56.043 回答