简体   繁体   English

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

[英]class method where self if used within a block

I've got a class method that uses dispatch_once to create a static object. 我有一个使用dispatch_once创建静态对象的类方法。 Inside the dispatch_once block I use [self class] and was wondering if I need to use a weak reference to self to avoid a retain cycle? 里面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;
}

If I use a weak reference to self I get a warning: 如果我使用弱引用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;
}

Incompatible pointer types initializing 'TUAccount *__weak' with an expression of type 'const Class' 不兼容的指针类型使用类型为'const Class'的表达式初始化'TUAccount * __ weak'

Because I get a warning I don't think I need to use a weak reference to self in this case but I wanted to see what you guys thought. 因为我得到了一个警告,我认为在这种情况下我不需要使用对self的弱引用,但我想看看你们的想法。

There is no reason to worry about a retain cycle here, because it's meaningless to retain or release a class object -- retain and release simply have no effect. 这里没有理由担心保留周期,因为保留或释放类对象没有意义 - 保留和释放根本没有效果。

Your attempt at making a weak reference is wrong, because you are taking a class object self and trying to cast it to an instance of TUAccount . 您尝试进行弱引用是错误的,因为您正在将类对象self并尝试将其转换为TUAccount实例 The two are completely different things. 这两者是完全不同的东西。

Also, you can simplify: 此外,您可以简化:

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

Since self is already a class, [self class] == self, so do this instead: 由于self已经是一个类,[self class] == self,所以这样做:

names = [[self accounts] allKeys];

I have checked one more time iOS SDK Docs and found next: 我已经再次检查了iOS SDK Docs并找到了下一个:

Objective-C Objects Objective-C对象

In a manually reference-counted environment, local variables used within the block are retained when the block is copied. 在手动引用计数环境中,复制块时将保留块中使用的局部变量。 Use of instance variables within the block will cause the object itself to be retained. 在块中使用实例变量将导致保留对象本身。 If you wish to override this behavior for a particular object variable, you can mark it with the __block storage type modifier. 如果要为特定对象变量覆盖此行为,可以使用__block存储类型修饰符对其进行标记。

If you are using ARC, object variables are retained and released automatically as the block is copied and later released. 如果使用ARC,则会在复制块并稍后释放时自动保留和释放对象变量。

  • Note: In a garbage-collected environment, if you apply both __weak and __block modifiers to a variable, then the block will not ensure that it is kept alive. 注意:在垃圾收集环境中,如果同时将__weak和__block修饰符应用于变量,则该块将无法确保它保持活动状态。

If you use a block within the implementation of a method, the rules for memory management of object instance variables are more subtle: 如果在方法的实现中使用块,则对象实例变量的内存管理规则更加微妙:

  • If you access an instance variable by reference, self is retained; 如果通过引用访问实例变量,则保留self;
  • If you access an instance variable by value, the variable is retained. 如果按值访问实例变量,则保留变量。

The following examples illustrate the two different situations: 以下示例说明了两种不同的情况:

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);
});

Conclusion: I assume that there is no problem with using self in block. 结论:我认为在块中使用self没有问题。 It will be retained and after execution released. 它将被保留并在执行后释放。

Moreover, you are not storing block in memory and using it directly. 此外,您不是将块存储在内存中并直接使用它。 So it is copied to the heap, executed and pushed from it. 因此它被复制到堆中,执行并从中推送。 I don't see any retain cycles. 我没有看到任何保留周期。

Hope I am right! 希望我是对的!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM