【问题标题】:Does referencing a singleton's sharedInstance create a retain cycle?引用单例的 sharedInstance 是否会创建保留周期?
【发布时间】:2015-09-09 20:47:28
【问题描述】:

假设我有以下单身人士:

@interface ABCSingleton: NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) ABCViewController *mainViewController;
@end

@implementation ABCSingleton
+ (ABCSingleton *)sharedInstance {
    static ABCSingleton *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [ABCSingleton new];
    });
    return instance;
}
- (void)doSomething {
}
@end

如果 doSomething 包含此代码:

- (void)doSomething {
    self.mainViewController.tapBlock = ^() {
        self.name = @"abc";
    };
}

...它将创建一个保留循环,因为 ABCSingleton 拥有 mainViewController,而 mainViewController 拥有 tapBlock,后者拥有 ABCSingleton。

如果我不使用 self 而是使用 sharedInstance 会怎样?

- (void)doSomething {
    self.mainViewController.tapBlock = ^() {
        [ABCSingleton sharedInstance].name = @"abc";
    };
}

它还会创建一个保留周期吗? (解释为什么,或者为什么不,将不胜感激!)

【问题讨论】:

  • 这将导致一个保留周期,但您应该问问自己,单例的保留周期是否重要。您为它定义了一个强静态引用,因此它永远不会消失。
  • @Fabian:很好,我更新了示例以说明为什么我特别希望不创建保留周期。我不希望 mainViewController 永远留在内存中。
  • 同样,保留周期无关紧要。 @property (nonatomic, strong) ABCViewController *mainViewController; 将使 mainViewController 永远不会被释放,除非你在某处明确地把它设为 nil。

标签: ios objective-c retain-cycle


【解决方案1】:

针对具体问题,这是第一种情况下的retain循环,相当于第二种情况下的retain循环(相当于mainViewController永远不会被释放)。

这表明存在更深层次的设计问题。单例永远不应该引用视图控制器。单例本质上是模型对象。模型对象不应该直接引用控制器对象。有关介绍,请参阅Model-View-Controller。这是 Cocoa 中的一个关键设计模式。

相反,视图控制器应该知道模型(在本例中为单例)。 doSomething 应该修改模型,当视图控制器出现在屏幕上时,应该读取模型以设置 tapBlock。视图控制器还可以在模型在屏幕上时观察模型(通过 KVO、通知或委托),以了解何时更改其值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-21
    • 1970-01-01
    • 1970-01-01
    • 2017-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多