2015-12-04 85 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;