0x0.問題導(dǎo)入:weak與strong在控件定義時的糾結(jié)
weak與strong在控件定義過程中時常用到掂之,通常使用xib拖動出來的使用weak宛官,純代碼編寫也有使用weak也有strong,如下:
@property (weak, nonatomic) IBOutlet UILabel *weakLabel;
@property (weak, nonatomic) UILabel *weakLabel2;
@property (strong, nonatomic) UILabel *strongLabel;
這三種各自的區(qū)別在哪,接著來實驗一下:
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *weakLabel;
@property (weak, nonatomic) UILabel *weakLabel2;
@property (strong, nonatomic) UILabel *strongLabel;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//控件初始化
UILabel *labTemp = [[UILabel alloc]init];
labTemp.frame = CGRectMake(50, 60, 100, 21);
labTemp.text = @"weakLabel2";
self.weakLabel2 = labTemp;
//如果labTemp沒有addSubview到self.view中,_weakLabel2將在viewDidLoad執(zhí)行完后釋放
[self.view addSubview:labTemp];
[self.view addSubview:self.strongLabel];
/*
代碼實現(xiàn)控件弱引用,提示: ("Warning: Assigning retained object to weak variable; object will be released after assignment")
這是因為對象沒有擁有者,在創(chuàng)建之后就會被立即釋放
*/
// _weakLabel2 = [[UILabel alloc]init];
// _weakLabel2.frame = CGRectMake(50, 60, 100, 21);
// _weakLabel2.text = @"weakLabel2";
// [self.view addSubview:_weakLabel2];
//1.對三種定義方式進行移除
[self.weakLabel removeFromSuperview];
[self.weakLabel2 removeFromSuperview];
[self.strongLabel removeFromSuperview];
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
//2.移除后進行添加[之所以放這方法測試技竟,是因為remove后有釋放延遲]
[self.view addSubview:_weakLabel];
[self.view addSubview:_weakLabel2];
[self.view addSubview:_strongLabel];
NSLog(@"_weakLabel --> %@",_weakLabel);
NSLog(@"_weakLabel2 --> %@",_weakLabel2);
NSLog(@"_strongLabel --> %@",_strongLabel);
}
#pragma mark - getter
-(UILabel*)strongLabel{
if(!_strongLabel){
_strongLabel = [[UILabel alloc]init];
_strongLabel.text = @"strongLabel";
_strongLabel.frame = CGRectMake(50, 100, 100, 21);
}
return _strongLabel;
}
@end
結(jié)果
0x1.weak與strong關(guān)鍵字特性
弱引用weak,即當(dāng)對象在釋放之后晚胡,指針地址被置為nil
強引用strong灵奖,進行retain+1操作嚼沿,對象持有
0x2.controller中控件生命周期
IB中outlet的控件:UIViewController->UIView->subView->UILabel
@property(null_resettable, nonatomic,strong) UIView *view;
UIViewController中self.view是個strong類型,當(dāng)系統(tǒng)將
@property (weak, nonatomic) IBOutlet UILabel *weakLabel;
add到self.view時瓷患,也就是說weakLabel已經(jīng)被強引用一次骡尽,所以一般不再使用strong進行修飾;當(dāng)控制器釋放時擅编,view也會被釋放攀细,weakLabel同樣。weak類型的控件:UIViewController->UIView->subView->UILabel
@property (weak, nonatomic) UILabel *weakLabel2;
其實就是IB的代碼編寫的實現(xiàn)爱态,內(nèi)存管理方式是一樣的strong類型的控件:
UIViewController->UIView->subView->UILabel
UIViewController->UILabel
@property (strong, nonatomic) UILabel *strongLabel;
因此當(dāng)strongLabel在view移除后谭贪,controller還對其進行保持
0x3.weak與strong場景使用
- 場景1:IB中多狀態(tài)UI布局方式(所以IB還是個好東西,可視化程度高锦担,節(jié)省很多時間)
//@property (strong, nonatomic) IBOutlet UIView *statusView1;
//@property (strong, nonatomic) IBOutlet UIView *statusView2;
@property (weak, nonatomic) IBOutlet UIView *statusView1;
@property (weak, nonatomic) IBOutlet UIView *statusView2;
這里就會出現(xiàn)兩種情況:
一是主容器view里面的label可以直接為weak俭识,其它兩個view也為weak
當(dāng)狀況view1、2初始化完成后洞渔,在viewDidLoad方法里面沒有add到self.view中套媚,當(dāng)數(shù)據(jù)load回來要更新狀態(tài)時,會發(fā)現(xiàn)view1磁椒、2已經(jīng)為nil了
二是其它兩個view為strong
這種情況就很明了堤瘤,跟代碼strong是一個道理,跟隨控制器生命周期
- 場景2:weak與strong代碼布局使用
1.懶加載浆熔,使用strong本辐。
為什么不使用weak,getter實現(xiàn)的時候医增,對象不持有慎皱。
@property (strong, nonatomic) UILabel *strongLabel;
-(UILabel*)strongLabel{
if(!_strongLabel){
_strongLabel = [[UILabel alloc]init];
_strongLabel.text = @"strongLabel";
_strongLabel.frame = CGRectMake(50, 100, 100, 21);
}
return _strongLabel;
}
2.weak定義
@property (weak, nonatomic) UILabel *weakLabel2;
注: 如果labTemp沒有addSubview到self.view中,_weakLabel2將在viewDidLoad執(zhí)行完后釋放
UILabel *labTemp = [[UILabel alloc]init];
labTemp.frame = CGRectMake(50, 60, 100, 21);
labTemp.text = @"weakLabel2";
self.weakLabel2 = labTemp;
[self.view addSubview:labTemp];
最后
引用知乎的一句話 余暢
因為控件他爹( view.superview )已經(jīng)揪著它的小辮了( strong reference )叶骨,你( viewController )眼瞅著( weak reference )就好了宝冕。
當(dāng)然,如果你想在 view 從 superview 里面 remove 掉之后還繼續(xù)持有的話邓萨,還是要用 strong 的( 你也揪著它的小辮, 這樣如果他爹松手了它也跑不了 )菊卷。