首页 > 代码库 > 【iOS开发系列】XIB IBOutlets use strong or weak ?

【iOS开发系列】XIB IBOutlets use strong or weak ?

有人问。在ARC下,IBOutlets究竟应该定义成strong 还是 weak ?支持这个答案的人最多。答案仅是摘自官方文档的一个片段:

 

From a practical perspective, in iOS and OS X outlets should be defined as declared properties. Outlets should generally be weak, except for those from File’s Owner to top-level objects in a nib file (or, in iOS, a storyboard scene) which should be strong. Outlets that you create will therefore typically be weak by default, because:

  • Outlets that you create to, for example, subviews of a view controller’s view or a window controller’s window, are arbitrary references between objects that do not imply ownership.

  • The strong outlets are frequently specified by framework classes (for example, UIViewController’s view outlet, or NSWindowController’s window outlet).

  • 大意是说。在 ARC 中,一般outlet属性都推荐使用 weak,应该使用 strong 的 outlet 是 File‘s Owner连接到 nib 的顶层对象。 

什么是 File‘s Owner连接到 nib 的顶层对象呢?说白话一点。就是自己定义的view,不是直接作为main view里面一个sub view直接显示出来。而是须要通过实例化创建出来的。

你自己实例化。当然须要strong了,不然谁还替你保留对象全部权呢?


以上的分析都没有错,可是总认为少了点什么。

对于究竟是weak 还是 strong,归根结底,还是要刨到对对象全部权的问题上,可是不便于总结出浅显易懂的规律性使使用方法则。于是。就会有一个又一个的特例打破文档所总结的常规,不明确规则的是什么,还是会碰到麻烦的。


我来举一个简单的样例,创建一个程序入口指向navigation controller的project,导航栏上拖2个button:

技术分享

右側button用于控制相机button的显示与否。依照文档的指示。我们在程序中定义这两个button应为weak属性

 

#import   
  
@interface TestViewController : UIViewController  
{  
    BOOL isShowing;  
}  
@property (nonatomic,weak)IBOutlet UIBarButtonItem *controlBtn;  
@property (nonatomic,weak)IBOutlet UIBarButtonItem *cameraBtn;  
-(IBAction)controlAction:(id)sender;  
@end 

用右側button,控制相机button的隐藏和显示:

 

#import "TestViewController.h"    
@interface TestViewController ()   
@end  
  
@implementation TestViewController  
@synthesize cameraBtn,controlBtn;  
  
- (void)viewDidLoad  
{  
    [super viewDidLoad];  
    // Do any additional setup after loading the view, typically from a nib.  
    isShowing = YES;  
}   
  
-(IBAction)controlAction:(id)sender  
{  
    if (isShowing) {  
        self.controlBtn.title = @"显示相机";  
        self.navigationItem.leftBarButtonItem = nil;  
        isShowing = NO;  
    }else {  
        self.controlBtn.title = @"隐藏相机";  
        self.navigationItem.leftBarButtonItem = cameraBtn;  
        isShowing = YES;  
    }  
}  
@end 


实验结果是。第一次隐藏了相机button后,就再也显示不出来了。原因非常easy,cameraBtn指向了空。我们丢失了cameraBtn的对象全部权。

解决这个问题的办法有两个:

1.不在xib或者storyboard上拖相机button,而是用代码创建,自己控制对象全部权

2.将 cameraBtn 定义为strong

我想强调的当然是另外一种方法


顺便提一下ARC其它属性的规则:

  • strong:等同于"retain",属性成为对象的拥有者

  • weak:属性是 weak pointer,当对象释放时会自己主动设置为 nil

  • unsafe_unretained:等同于之前的"assign",仅仅有 iOS 4 才应该使用

  • copy:和之前的 copy 一样,复制一个对象并创建 strong 关联

  • assign:对象不能使用 assign,但原始类型(BOOL、int、float)仍然能够使用 

【iOS开发系列】XIB IBOutlets use strong or weak ?