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

标签 objective-c memory-management singleton

我有一个名为MyManager的单例类。我在其 block 内使用 self:requestSomeInfo 和 requestSomeInfoWithString。 requestSomeInfoWithString 方法获取 self.string 作为参数。 此代码是否会导致两个 block 中出现循环保留?

该项目是与 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

最佳答案

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

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

因此,从 MyManager 方法中将恢复的 block 引用存储到实例变量中的点开始,您将拥有以下引用链:

shared -> your MyManager instance

the MyManager instance -> the passed in block

the passed block -> references the MyClass instance which created it

这不是引用循环,因此除非您在实际代码中有更多对象间引用,否则就没有循环。

引用循环本身并不坏,它们可以在正常的程序执行过程中创建,有时对于保持适当的对象处于事件状态可能至关重要;一个循环可以是临时的/具有有限的生命周期,之后该循环中的至少一个链接被破坏。当引用循环无意中导致对象实例超出其所需的生命周期时,它才会成为坏的保留循环...

这最终让我们看到了您的代码。您有一个 MyManager共享实例,它可能从创建时起一直存在到程序完成为止。在这种情况下,您存储对 block 的引用,而这些 block 存储对 MyClass 实例的引用...这是您可能会无意中“泄漏”的地方;如果您的 MyManager 方法在不再需要这些引用时(可能在调用引用的 block 后立即)不会删除(将 nil 存储到)引用这些 block 的实例变量那么您可能会长期无意地引用早已被丢弃的 MyClass 实例。删除那些曾经使用过的 block 引用,这种可能性就消失了。

希望一切都有意义!

关于objective-c - Objective-C 中使用单例保留循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52752181/

相关文章:

java - 有没有办法通过方法回调在代码中捕获 Java 中的对象分配?

单线程 Wcf 单例

c++ - 引用单例是在栈上还是在堆上?

ios - 在没有 Game Center 的 iOS 应用程序中实现成就

iphone - 获取所有 UITextField 的数组

Mysql- "SELECT field "确实将内存填充为 "SELECT * "吗? - 因诺数据库

objective-c - Objective-C ,iOS : not calling alloc or init on a subview

objective-c - 如何使用 va_args 传递参数(可变参数,省略号)

objective-c - 动态改变 UITableViewCell 的附属 View 图像

oop - 名为 `User` 的类应该是单例模式的实现吗?