Reputation: 91681
Say I have the following singleton:
@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
If doSomething contained this code:
- (void)doSomething {
self.mainViewController.tapBlock = ^() {
self.name = @"abc";
};
}
... it would create a retain cycle since ABCSingleton owns mainViewController, which owns tapBlock, which owns ABCSingleton.
What if instead of using self, I used sharedInstance?
- (void)doSomething {
self.mainViewController.tapBlock = ^() {
[ABCSingleton sharedInstance].name = @"abc";
};
}
Would it still create a retain cycle? (An explanation as to why, or why not, would be appreciated!)
Upvotes: 0
Views: 300
Reputation: 299325
To the specific question, this is a retain loop in the first case, and equivalent to a retain loop in the second case (equivalent in that mainViewController
will never be released).
This indicates a deeper design problem. A singleton should never reference a view controller. Singletons are by nature model objects. Model objects should never reference controller objects directly. See Model-View-Controller for an introduction. This is a key design pattern in Cocoa.
Instead, the view controller should know about the model (the singleton in this case). doSomething
should modify the model, and the view controller, when it comes on the screen, should read the model to set tapBlock
. The view controller can also observe the model (via KVO, notifications, or delegation) while it is onscreen to know when to change its values.
Upvotes: 2