2015-10-06 126 views
1

考慮我在我的視圖控制器中,我添加了Singleton屬性的RACObserve,並且在subscribNext中我有一個自引用。 的代碼如下:爲什麼此RACObserve塊導致保留循環?

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

根據我的理解,自己不持有塊的強引用(而塊持有強烈的自我參照),這應該不會造成保留週期。 我已閱讀反應可可的內存管理以及https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/Documentation/Legacy/MemoryManagement.md 在他們提供一個例子作爲

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

我完全理解爲什麼它造成上述情況下的保留週期,我們需要的塊內弱的自我。 我很困惑,爲什麼在第一種情況下,它會導致一個保留週期。爲了確認這一點,只需將該代碼片段粘貼到viewDidLoad後面,並查看視圖控制器是否應該在何時解除分配。 如果你需要看到單身的多個實現,這是代碼,

@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 

任何賜教這件事嗎?

+1

它不是一個真正的循環,但單永遠不會被釋放,由於是單身,所以對你的視圖控制器持有強烈的參考的塊永遠不會放棄那個參考。 – dan

+0

@dan爲什麼不作爲回答發佈? :) – mattsson

+0

感謝@dan我想我現在得到它,這意味着這個subscribeNext塊不像我們的正常定義的塊(這是block執行後dealloc),我是否正確地說? –

回答

4

內部實現相當複雜,是否存在真正的保留週期並不重要。

這裏爲什麼內存泄漏是隻在你的兩個實施例中的相同的原因:

  1. self
  2. 的塊通過
  3. 訂戶被保持內部訂戶對象保持的塊保留通過RACObserve信號的一些內部信息直到信號終止。
  4. 當目標(單實例實例)或self(RACObserve微內存使用self)被釋放時,RACObserve信號終止。

但是現在單例實例不會釋放,並且self也不會釋放,因爲它已經被保留了。所以信號永遠不會終止,然後內存泄漏。

0

無論如何,你應該寫這樣的事情

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

相反,寫

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