我有一个使用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
的引用,但我想看看你们的想法。
答案 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
没有问题。它将被保留并在执行后释放。
此外,您不是将块存储在内存中并直接使用它。因此它被复制到堆中,执行并从中推送。我没有看到任何保留周期。
希望我是对的!