Reputation: 187
I have a singleton class named MyManager
. I use self inside of its blocks: requestSomeInfo and requestSomeInfoWithString.
And requestSomeInfoWithString method gets self.string as a parameter.
Does this code lead to retain cycles in both the blocks?
The project is with ARC.
@interface MyManager : NSObject
+ (instancetype)sharedInstance;
- (void)requestSomeInfo:(void (^)(BOOL success))completion;
- (void)requestSomeInfoWithString:(NSString *)string completion:(void (^)(BOOL success))completion;
@end
@implementation MyManager
+ (instancetype)sharedInstance {
static MyManager *shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [MyManager new];
});
return shared;
}
@end
@interface MyClass
@property string;
@end
@implementation MyClass
.....
[[MyManager sharedInstance] requestSomeInfo:^(BOOL success) {
if (success) {
[self someAction];
}
}];
[[MyManager sharedInstance] requestSomeInfoWithString:self.string completion:^(BOOL success) {
if (success) {
[self someAction];
}
}];
.....
@end
Upvotes: 2
Views: 168
Reputation: 53000
Your description does not mention MyClass
but your code fragment does. Going by the code fragment you have methods in MyClass
which makes calls to methods in MyManager
. These calls directly pass blocks as arguments, without themselves storing references in instance variables to those blocks; you do not show whether MyManager
stores references to the blocks it receives in its instance variables but it is reasonable to assume that it does.
The blocks that are passed use self
, which references the instance of MyClass
that created the block.
So from the point within the MyManager
methods where they store the revived block references into instance variables you have the following chain of references:
shared
-> yourMyManager
instancethe
MyManager
instance -> the passed in blockthe passed block -> references the
MyClass
instance which created it
That's not a reference cycle, so unless you have more inter-object references in your real code you don't have a cycle.
A reference cycle is not itself bad, they can get created during the course of normal prgogram execution and sometimes might be vital to keep the appropriate objects alive; a cycle may be temporary/of finite lifetime after which at least one of the links in the cycle is broken. A reference cycle only becomes the bad retain cycle when they unintentionally result in object instances living beyond their required lifetime...
Which finally brings us to your code. You have a shared instance of MyManager
which probably lives from its point of creation until your program finishes. In that instance you Store references to blocks, and those blocks Store references to MyClass
instances... This is somewhere where you might have an inadvertent "leak"; if your MyManager
methods do not erase (store nil
into) the instance variables that reference those blocks once those references are no longer required (probably immediately after the referenced block is invoked) then you could have long term unintentional references to MyClass
instances that have long been otherwise discarded. Erase those block references once used and the possibility vanishes.
Hope that all makes sense!
Upvotes: 2