以前在沒有ARC(automatic reference counting)的時候我們使用assign與retain來修飾屬性娱挨,后來引入了更安全的weak和strong來修飾屬性
一抖苦、探討assign毯侦、retain洒缀、strong瑰谜、weak的區(qū)別
assign與weak
兩者都是弱引用,assign通常用于普通類型屬性(如int,NSInteger)树绩,常見的還會用于delegate對象的屬性修飾萨脑,基本上來說兩者是可以通用的。
Q:那對于delegate的屬性修飾符到底是用assign好饺饭,還是weak好呢砚哗?
分析:weak在引用的對象被釋放的時候會將delegate置為nil
,而assign修飾的delegate依然會指向原來的位置砰奕,這樣在delegate引用的對象被釋放后蛛芥,delegate就會變成野指針提鸟。在OC中你給你一個nil對象發(fā)送消息不會crash,但是給一個對象(如:野指針)發(fā)送他不能響應(yīng)的消息是會crash的仅淑,所以總的來說weak要比assign安全一些称勋。
A:像delegate屬性的修飾符建議用weak修飾而不是assign,這樣你使用delegate的時候就不需要判斷delegate對象是不是存在了涯竟。
retain和strong
他倆都是強引用赡鲜,除了某些情況下不一樣,比如修飾block庐船,其他的時候也是可以通用的银酬。
關(guān)于修飾block的時候,retain和strong有什么區(qū)別請看下面??
二筐钟、探討block的屬性修飾符
提示一下揩瞪,現(xiàn)在的Xcode創(chuàng)建的新項目都是默認(rèn)采用ARC,我們?nèi)绻胍獙こ踢M行手動內(nèi)存管理該怎么辦篓冲?我們可以在TARGET -> Build Settings 下搜索Garbage Collection李破,會搜出Objective-C Automatic Reference Counting,將其設(shè)置為NO即可使整個工程處于MRC環(huán)境下了壹将。那如果只想對某個類文件采用MRC嗤攻,工程的其他類都用ARC呢,那我們可以在TARGET -> Build Phase -> Compile Sources下找到對應(yīng)的類诽俯,雙擊修改Compiler flag妇菱,然后添加-fno-objc-arc
即可,反之在MRC工程下的某個類中添加-fobjc-arc
即可使用ARC暴区。
MRC下
(1)用retain修飾block 且 不訪問 external變量情況下
@interface ViewController ()
@property (nonatomic, retain) TestBlock block;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
__block NSInteger num = 1;
self.block = ^{
//num = 2;
};
NSLog(@"---%@",self.block);
}
@end
打印結(jié)果:
---<__NSGlobalBlock__: 0x1008b9088>
(2)用retain修飾block 且 訪問 external變量情況下
@interface ViewController ()
@property (nonatomic, retain) TestBlock block;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
__block NSInteger num = 1;
self.block = ^{
num = 2;
};
NSLog(@"---%@",self.block);
}
@end
打印結(jié)果:
---<__NSStackBlock__: 0x7ffeeb094988>
(3)用strong或copy修飾block 且 不訪問 external變量情況下
@interface ViewController ()
@property (nonatomic, strong) TestBlock block;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
__block NSInteger num = 1;
self.block = ^{
//num = 2;
};
NSLog(@"---%@",self.block);
}
@end
打印結(jié)果:
---<__NSGlobalBlock__: 0x10781c098>
(4)用strong或copy修飾block 且 訪問 external變量情況下
@interface ViewController ()
@property (nonatomic, strong) TestBlock block;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
__block NSInteger num = 1;
self.block = ^{
num = 2;
};
NSLog(@"---%@",self.block);
}
@end
打印結(jié)果:
---<__NSMallocBlock__: 0x600002e4e5e0>
ARC下
(1)用retain修飾block 且 不訪問 external變量情況下
@interface ViewController ()
@property (nonatomic, retain) TestBlock block;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
__block NSInteger num = 1;
self.block = ^{
//num = 2;
};
NSLog(@"---%@",self.block);
}
@end
打印結(jié)果:
---<__NSGlobalBlock__: 0x10f4b30a0>
(2)用retain修飾block 且 訪問 external變量情況下
@interface ViewController ()
@property (nonatomic, retain) TestBlock block;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
__block NSInteger num = 1;
self.block = ^{
num = 2;
};
NSLog(@"---%@",self.block);
}
@end
打印結(jié)果:
---<__NSMallocBlock__: 0x600002c78120>
(3)用strong或copy修飾block 且 不訪問 external變量情況下
@interface ViewController ()
@property (nonatomic, strong) TestBlock block;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
__block NSInteger num = 1;
self.block = ^{
//num = 2;
};
NSLog(@"---%@",self.block);
}
@end
打印結(jié)果:
---<__NSGlobalBlock__: 0x10ff380a8>
(4)用strong或copy修飾block 且 訪問 external變量情況下
@interface ViewController ()
@property (nonatomic, strong) TestBlock block;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
__block NSInteger num = 1;
self.block = ^{
num = 2;
};
NSLog(@"---%@",self.block);
}
@end
打印結(jié)果:
---<__NSMallocBlock__: 0x60000075a550>
結(jié)果對照表(訪問:指的是訪問external變量恶耽,反之亦然):
retain 不訪問 | strong(copy)不訪問 | retain 訪問 | strong(copy)訪問 | |
---|---|---|---|---|
MRC | NSGlobalBlock | NSGlobalBlock | NSStackBlock |
NSMallocBlock |
ARC | NSGlobalBlock | NSGlobalBlock | NSMallocBlock | NSMallocBlock |
結(jié)論
- 只要不引入external變量,無論是
MRC
還是ARC
颜启,無論是retain
還是strong
修飾block偷俭,block屬性都是存在全局?jǐn)?shù)據(jù)區(qū) - 引入external變量時,retain和strong(copy)是有區(qū)別的缰盏,
在MRC
時涌萤,block存在棧區(qū)(stack)的,因此使用的時候要注意此時的block是否還存在口猜,以免操作了野指針而閃退负溪。
在ARC
時,block是存在堆區(qū)(heap)的济炎。
總結(jié)
- 所以說block的屬性修飾符應(yīng)該用
strong
或copy
比較安全些川抡。 - 對block來說,屬性修飾符用
strong
或copy
效果是一樣的。
【注意】上述提到的external變量
不是指C語言上的那個external變量崖堤,本處指的是block外面變量侍咱,可以是局部變量
,也是是一個屬性
密幔。