2015-12-04 109 views
1

我有__弱自我引用。控制器2和控制器3是否需要參考競爭區塊中的__weak參考?__自我阻止

UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 

id controller1 = [sb instantiateViewControllerWithIdentifier:@"controller1"]; 

id controller2 = [sb instantiateViewControllerWithIdentifier:@"controller2"]; 

id controller3 = [sb instantiateViewControllerWithIdentifier:@"controller3"]; 

__weak typeof(self) weakSelf = self; 

[self presentViewController:controller1 animated:YES completion:^{ 

    [(UINavigationController *)weakSelf.parentViewController setViewControllers:@[controller2, controller3] animated:NO]; 

}]; 

編輯什麼下面的代碼?以下代碼中的塊是否需要對自我的弱引用?

typedef void(^MyCustomBlock)(void); 

@property (strong, readwrite, nonatomic) MyCustomBlock customBlock; 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    __weak typeof(self) weakSelf = self; 
    self.customBlock = ^{ 
     [(UINavigationController *)weakSelf.parentViewController setViewControllers:@[controller2, controller3] animated:NO]; 
    }; 
    [self presentViewController:controller1 animated:YES completion:self.customBlock]; 
} 
+0

你想做什麼?這將提供一個視圖控制器,然後立即更改導航控制器顯示的視圖控制器(您應該通過'self.navigationController',BTW) – jcaron

+0

忘記應用程序邏輯。我是否需要添加行:__weak typeof( controller1)weakController1 = controller1; __weak typeof(controller2)weakController2 = controller2? – Adobels

+1

如果你需要它們,編譯器會告訴你。通常只有當你引用自我或實例變量(隱含引用self)時才需要它們。 – jcaron

回答

3

其無害的(在這種情況下)聲明和使用weak副本,但塊的引用沒有必須weak

問題是常見誤解的症狀:塊引用的所有對象都被作爲塊的強引用(保留)來維護。如果任何這些對象反過來保持對塊的強烈引用,那麼你就有一個保留週期。

就像它的聲音,一個保留週期是當物體強烈的相互引用,無論是直接:

block ---> objectA ---> block ("--->" means retains) 

...或間接:

block ---> objectA ---> objectB ---> block 

保留週期是不好的,因爲系統不會釋放由其他對象保留的對象。因此,當我們嘗試釋放塊時,我們不能因爲(在直接情況下)它由objectA保留,並且我們不能釋放objectA,因爲它由塊保留。

簡單的修復方法是聲明一個weak指針的副本,告訴塊本質上「不保留這個對象,我保證它會超出塊」。

看着OP代碼,傳遞給presentViewController的塊根本不被保留。它足夠長,可以完成演示,在動畫完成後調用,然後丟棄。由於塊中引用的對象都沒有保留該塊的副本,因此不存在保留週期的風險,並且完全不需要任何引用。

// initialize controller1, 2, 3 

// no need for this 
//__weak typeof(self) weakSelf = self; 

[self presentViewController:controller1 animated:YES completion:^{ 
    // perfectly safe... 
    [(UINavigationController *)self.parentViewController setViewControllers:@[controller2, controller3] animated:NO]; 
}]; 

編輯 關於在編輯附加代碼:是的,在這種情況下,因爲你保留塊與塊是指自我,弱副本必須在使用,以避免保留週期。

+0

這是一個很好的例子嗎?typedef void(^ MyCustomBlock)(void); @property(strong,readwrite,nonatomic)MyCustomBlock customBlock; __弱類型(self)weakSelf = self; self.customBlock =^{ [weakSelf.navigationController setNavigationBarHidden:NO]; [weakSelf.navigationController popViewControllerAnimated:NO]; }; – Adobels

+0

@adobels,對不起,我不理解評論,這看起來像你想要一個弱引用的例子。但它與OP中的代碼不同。 – danh

+0

檢查這一個typedef void(^ MyCustomBlock)(void); @property(strong,readwrite,nonatomic)MyCustomBlock customBlock; (自我)weakSelf = self;(自我)weakSelf = self;(自我)weakSelf = self; self.customBlock =^{ \t [(UINavigationController *)weakSelf.parentViewController setViewControllers:@ [controller2,controller3] animated:NO]; }; [self presentViewController:controller1 animated:YES completion:self.customBlock]; } – Adobels

0

就像@ danh的回覆一樣,當你聲明一個塊屬性時,將它作爲副本,因爲塊在堆棧上啓動,並且需要將它們移動到堆中以保持對它們的強引用。

typedef void(^MyCustomBlock)(void); 

@property (nonatomic, copy) MyCustomBlock customBlock;