使用Objective-C中的单例保留循环

问题描述 投票:2回答:1

我有一个名为MyManager的单例类。我在其块中使用self:requestSomeInfo和requestSomeInfoWithString。 requestSomeInfoWithString方法将self.string作为参数。这段代码是否导致两个块中都保留了循环?

该项目是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
objective-c memory-management singleton
1个回答
2
投票

你的描述没有提到MyClass但你的代码片段没有。通过代码片段,您可以在MyClass中使用方法调用MyManager中的方法。这些调用直接将块作为参数传递,而不会将实例变量中的引用存储到这些块中;你没有显示MyManager是否存储对它在实例变量中接收的块的引用,但是可以合理地假设它存在。

传递的块使用self,它引用创建块的MyClass实例。

因此,从MyManager方法中将复活的块引用存储到实例变量中的点,您有以下引用链:

shared - >你的MyManager实例

MyManager实例 - >传入块

传递的块 - >引用创建它的MyClass实例

这不是一个参考周期,所以除非你的实际代码中有更多的对象间引用,否则你没有一个循环。

参考周期本身并不坏,它们可以在正常的prgogram执行过程中创建,有时可能对于保持适当的对象存活至关重要;循环可以是暂时的/有限的寿命,之后循环中的至少一个链路被破坏。参考周期只会在无意中导致对象实例超出其所需的生命周期时变为不良保留周期...

这最终将我们带到您的代码中。你有一个MyManager的共享实例,它可能从它的创建点开始直到你的程序结束。在那个例子中,你存储对块的引用,那些块存储对MyClass实例的引用......这是你可能无意中“泄漏”的地方;如果你的MyManager方法没有擦除(存储nil)引用那些块的实例变量一旦不再需要那些引用(可能是在引用的块被调用之后),那么你可能会长期无意中引用长的MyClass实例被丢弃了。擦除一旦使用的块引用,可能性消失。

希望一切都有道理!

© www.soinside.com 2019 - 2024. All rights reserved.