简体   繁体   English

为什么此RACObserve块导致保留周期?

[英]why this RACObserve block caused retain cycle?

Consider I in my view controller, I added RACObserve of property of Singleton, and inside subscribNext I have a self reference in it. 考虑到我在我的视图控制器中,我添加了Singleton属性的RACObserve,在subscribrib内部,我有一个自引用。 The code is as below: 代码如下:

[RACObserve([Singleton shared], singletonFlag) subscribeNext:^(NSNumber *singletonFlag) {
        self.flag = [singletonFlag boolValue];
    }];

Based on my understanding, self don't hold a strong reference of the block(while block hold a strong reference of self), this shouldn't cause retain cycle. 根据我的理解,self不持有该块的强引用(而block持有一个对self的强引用),这不应引起保留周期。 I have read memory management of reactive cocoa as well https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/Documentation/Legacy/MemoryManagement.md In which they provide an example as 我还阅读了反应性可可粉的内存管理https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/Documentation/Legacy/MemoryManagement.md ,其中提供了一个示例

[RACObserve(self, username) subscribeNext:^(NSString *username) {
    [self validateUsername];
}];

I totally understand why it caused the retain cycle in above case and we need a weak self inside the block. 我完全理解为什么它会导致上述情况下的保留周期,并且我们需要在块内具有较弱的自我。 I am confused why in the first case, it will cause a retain cycle. 我很困惑为什么在第一种情况下会导致保留周期。 To confirm this, just paste that code snippet after viewDidLoad and see whether the view controller was dealloc-ed when it should be. 要确认这一点,只需将该代码段粘贴在viewDidLoad之后,然后查看是否应在适当时候取消分配视图控制器。 If you need see more implementations of the singleton, this is the code, 如果您需要查看单例的更多实现,请使用以下代码:

@interface Singleton : NSObject
@property (readwrite,nonatomic) BOOL singletonFlag;
@end

@implementation Singleton
+ (Singleton *)shared {
    static dispatch_once_t pred = 0;
    __strong static id _sharedObject = nil;
    dispatch_once(&pred, ^{
        _sharedObject = [[self alloc] init];
    });
    return _sharedObject;
}

- (id)init {
    if (self = [super init]) {
        NSLog(@"init of %@",NSStringFromClass(self.class));
    }
    return self;
}
@end

Anyone enlighten me about this? 有人启发我吗?

The internal implementation is quite complicated, It's not important whether there is a real retain cycle. 内部实现非常复杂,是否存在真正的保留周期并不重要。

Here the reason why memory leaks is just the same in your two examples: 这里的内存泄漏原因在您的两个示例中是相同的:

  1. self is retained by the block self被块保留
  2. The block is retained by an internal subscriber object 该块由内部订户对象保留
  3. The subscriber is retained by some internal thing of the RACObserve signal until the signal terminates. 用户被RACObserve信号的某些内部事物保留,直到该信号终止。
  4. The RACObserve signal terminates when either the target (the singleton instance) or self (the RACObserve micro is implicitly using self ) is deallocated. 当释放目标(单例实例)或self (RACObserve微型隐式使用self )时,RACObserve信号终止。

But now the singleton instance won't dealloc, and self won't dealloc neither since it's already retained. 但是现在,单例实例不会取消分配,而self也不会取消分配,因为它已经被保留了。 So the signal never terminates, then memory leaks. 因此信号永远不会终止,然后内存泄漏。

Anyway, you shouldn't write such things as 无论如何,你不应该这样写

[RACObserve([Singleton shared], singletonFlag) subscribeNext:^(NSNumber *singletonFlag) {
  self.flag = [singletonFlag boolValue];
}];

Instead, write 相反,写

RAC(self, flag) = RACObserve([Singleton shared], singletonFlag);

The problem is that RACObserve() will return you a RACDisposable object, that you have to dispose your self. 问题在于RACObserve()将返回一个RACDisposable对象,您必须处置自己。 If you use it the way RAC()=RACObserve(), then the RAC() part will take care of killing the RACDisposable object that is returned by RACObserve() method. 如果以RAC()= RACObserve()的方式使用它,那么RAC()部分将负责杀死由RACObserve()方法返回的RACDisposable对象。

One quick fix that you can make when using the RACObserver like this: 使用RACObserver时可以进行以下快速修复:

[RACObserve(self, username) subscribeNext:^(NSString *username) {
[self validateUsername];

}]; }];

Is to turn it into this: (RACDisposable *disposableSignal; declared in .h for example) 要将其转换为:(RACDisposable * disposableSignal;例如在.h中声明)

disposableSignal=[RACObserve(self, username) subscribeNext:^(NSString *username) {
[self validateUsername];

}]; }];

And use [disposableSignal dispose] to deallocate the signal. 并使用[disposableSignal dispose]解除信号分配。 For example in viewWillDisappear method. 例如在viewWillDisappear方法中。 Basically you have to kill it with dispose method to get rid of it. 基本上,您必须使用dispose方法将其杀死以摆脱它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM