1.對(duì)屬性修飾符的理解
MRC下
assign
主要用于修飾基本數(shù)據(jù)類型孵奶,setter方法也只是簡(jiǎn)單的賦值伙狐,例如NSInter氓奈,CGFloat 如果用來(lái)修飾對(duì)象,并不持有對(duì)象蜓肆,那么對(duì)象的引用計(jì)數(shù)不變颜凯,如果這個(gè)時(shí)候?qū)ο蟊会尫帕四北遥涂赡艹蔀橐爸羔槪皇謩?dòng)置為nil装获,在堆上很容易造成崩潰瑞信,而如果修飾的不是對(duì)象厉颤,那么棧上的內(nèi)存系統(tǒng)會(huì)自動(dòng)處理穴豫,不會(huì)造成野指針
retain
修飾對(duì)象,不能修飾基本數(shù)據(jù)類型 逼友,引用計(jì)數(shù)+1精肃,適用于NSObject及子類
ARC下
Strong
對(duì)應(yīng)的setter方法是先release,然后再把參數(shù)retain帜乞,最后成員變量賦值司抱,類似于retain
表示指向并擁有對(duì)象,其修飾的對(duì)象引用計(jì)數(shù)會(huì)+1黎烈,該對(duì)象只要引用計(jì)數(shù)不為0則不會(huì)被銷毀习柠,當(dāng)然強(qiáng)行置為nil可以銷毀他
Copy
對(duì)應(yīng)的setter方法是先release,然后copy參數(shù)內(nèi)容照棋,創(chuàng)建一個(gè)新的內(nèi)存地址资溃,因此修改之前的地址不會(huì)修改到副本,減少對(duì)上下文的依賴烈炭,copy一般用于修飾具有可變應(yīng)用類型的不可變對(duì)象身上溶锭,例如NSArray,NSString符隙,NSDictionary趴捅,,為什么呢霹疫?看下例子
@property(nonatomic,strong) NSString *testStrongName;
@property(nonatomic,copy) NSString * testCopyName;
self.testStrongName = @"test1";
self.testCopyName = @"test1";
NSLog(@"strong====%@ p==== %p",self.testStrongName,self.testStrongName);
NSLog(@"copy======%@ p==== %p",self.testCopyName,self.testCopyName);
NSMutableString *mStr = [[NSMutableString alloc]initWithString:@"TestM2"];
self.testStrongName = mStr;
self.testCopyName = mStr;
NSLog(@"mStr==== %p",mStr);
[mStr appendString:@"111"];//mstr不改地址
NSLog(@"mStr==== %p",mStr);
mStr = [NSMutableString stringWithFormat:@"test2"];//mstr改地址
NSLog(@"mStr==== %p",mStr);
[mStr appendString:@"111"];
NSLog(@"strong====%@ p==== %p",self.testStrongName,self.testStrongName);
NSLog(@"copy======%@ p==== %p",self.testCopyName,self.testCopyName);
//打印結(jié)果為
2019-01-22 11:42:33.286277+0800 OC-test1[18667:237712] [default] Unable to load
Info.plist exceptions (eGPUOverrides)
2019-01-22 11:42:33.338443+0800 OC-test1[18667:237660] strong====test1 p====
0x100002058
2019-01-22 11:42:33.338476+0800 OC-test1[18667:237660] copy======test1
p==== 0x100002058
2019-01-22 11:42:33.338495+0800 OC-test1[18667:237660] mStr====
0x600000c053e0
2019-01-22 11:42:33.338511+0800 OC-test1[18667:237660] mStr====
0x600000c053e0
2019-01-22 11:42:33.338535+0800 OC-test1[18667:237660] mStr====
0x600000c05410
2019-01-22 11:42:33.338569+0800 OC-test1[18667:237660] strong====TestM2111
p==== 0x600000c053e0
2019-01-22 11:42:33.338584+0800 OC-test1[18667:237660] copy======TestM2
p==== 0x5f8f2f5af9a6eb4d
可以看到拱绑,本身是不可變類型NSString,但是它會(huì)有可變類型的屬性在丽蝎,如果你用Strong修飾他欺栗,當(dāng)該指針指向了NSMutableString類型的數(shù)據(jù),Strong只是把源數(shù)據(jù)的多了一個(gè)新的指針指向而已征峦,當(dāng)源數(shù)據(jù)改變迟几,那么原來(lái)設(shè)置的name不可變類型,就可以變了栏笆。這就是上面遇到修改之前的數(shù)據(jù)改變了現(xiàn)有的數(shù)據(jù)类腮,上下文依賴了,因此copy來(lái)減少上下文依賴蛉加,如果本身是不可變類型NSstring蚜枢,那么Strong也一樣缸逃,如果變成可變類型了,那么減少上下文依賴厂抽,copy就會(huì)對(duì)可變類型執(zhí)行深copy需频,從而讓數(shù)據(jù)源更干凈
strong和copy都會(huì)使引用計(jì)數(shù)加1,但strong使兩個(gè)指針指向同一個(gè)內(nèi)存地址筷凤,copy則會(huì)在內(nèi)存里拷貝一份對(duì)象昭殉,兩個(gè)指針指向不同的內(nèi)存地址
針對(duì)copy這個(gè)屬性,以string類型為例藐守,copy就是普通的指針copy(淺copy)挪丢,而mutableCopy就是內(nèi)容copy(深copy),如果是mutableString類型的話卢厂,那么copy就全是內(nèi)容copy了 如果是容器類型乾蓬,例如NSArray和NSDictionary,copy屬性操作的指針針對(duì)容器本身慎恒,而容器內(nèi)部的都還是同一個(gè)指針引用任内,并不會(huì)根據(jù)容器的copy或者strong而變化,指針根據(jù)自己的屬性修飾符有關(guān)
- weak 不會(huì)保留傳入的屬性融柬,不會(huì)使對(duì)象的引用計(jì)數(shù)+1死嗦,類似assign,但是當(dāng)對(duì)象被釋放時(shí)丹鸿,weak自動(dòng)置nil越走,這就是weak區(qū)別assgin最大的區(qū)別 小知識(shí):當(dāng)屬性是readwrite的時(shí)候,如果重寫(xiě)了getter的方法靠欢,那么setter方法是系統(tǒng)提供的廊敌,那么系統(tǒng)順便幫我們實(shí)現(xiàn)了成員變量,但是如果你重寫(xiě)了setter和getter方法门怪,那么這個(gè)時(shí)候你把系統(tǒng)的兩個(gè)方法都實(shí)現(xiàn)了骡澈,那么系統(tǒng)就需要你自己去實(shí)現(xiàn)成員變涼了,不然是無(wú)法獲取到的掷空,你可以再implementation或者extension里面進(jìn)行實(shí)現(xiàn)肋殴,或者在h文件實(shí)現(xiàn),前兩者是@private的坦弟,后者是共有的
weak 和 assign的理解
1.assign適用于基本數(shù)據(jù)類型护锤,weak是適用于NSObject對(duì)象,并且是一個(gè)弱引用酿傍。 2.assign其實(shí)也可以用來(lái)修飾對(duì)象烙懦。那么我們?yōu)槭裁床挥盟揎棇?duì)象呢?因?yàn)楸籥ssign修飾的對(duì)象(一般編譯的時(shí)候會(huì)產(chǎn)生警告:Assigning retained object to unsafe property; object will be released after assignment)在釋放之后赤炒,指針的地址還是存在的氯析,也就是說(shuō)指針并沒(méi)有被置為nil亏较,造成野指針。對(duì)象一般分配在堆上的某塊內(nèi)存掩缓,如果在后續(xù)的內(nèi)存分配中雪情,剛好分到了這塊地址,程序就會(huì)崩潰掉你辣。 3.那為什么可以用assign修飾基本數(shù)據(jù)類型巡通?因?yàn)榛A(chǔ)數(shù)據(jù)類型一般分配在棧上,棧的內(nèi)存會(huì)由系統(tǒng)自己自動(dòng)處理绢记,不會(huì)造成野指針扁达。 4.weak修飾的對(duì)象在釋放之后正卧,指針地址會(huì)被置為nil蠢熄。所以現(xiàn)在一般弱引用就是用weak。weak使用場(chǎng)景: 5.在ARC下,在有可能出現(xiàn)循環(huán)引用的時(shí)候炉旷,往往要通過(guò)讓其中一端使用weak來(lái)解決签孔,比如: delegate代理屬性,通常就會(huì)聲明為weak窘行。 自身已經(jīng)對(duì)它進(jìn)行一次強(qiáng)引用饥追,沒(méi)有必要再?gòu)?qiáng)引用一次時(shí)也會(huì)使用weak。比如:自定義 IBOutlet控件屬性一般也使用weak罐盔,當(dāng)然也可以使用strong但绕。
__block與__weak的區(qū)別
__block是用來(lái)修飾一個(gè)變量,這個(gè)變量就可以在block中被修改
__block:使用 __block修飾的變量在block代碼塊中會(huì)被retain(ARC下會(huì)retain惶看,MRC下不會(huì)retain)
__weak:使用__weak修飾的變量不會(huì)在block代碼塊中被retain
同時(shí)捏顺,在ARC下,要避免block出現(xiàn)循環(huán)引用 __weak typedof(self)weakSelf = self;
這兩個(gè)都是和block相關(guān)纬黎,block就是OC對(duì)閉包的實(shí)現(xiàn)幅骄,閉包就是匿名函數(shù),或者理解為指向函數(shù)的指針
block變量定義時(shí)為什么用copy本今?block是放在哪里的拆座?
block本身是像對(duì)象一樣可以retain,和release冠息。但是挪凑,block在創(chuàng)建的時(shí)候,它的內(nèi)存是分配在棧(stack)上逛艰,可能被隨時(shí)回收躏碳,而不是在堆(heap)上。他本身的作于域是屬于創(chuàng)建時(shí)候的作用域瓮孙,一旦在創(chuàng)建時(shí)候的作用域外面調(diào)用block將導(dǎo)致程序崩潰唐断。通過(guò)copy可以把block拷貝(copy)到堆选脊,保證block的聲明域外使用。
特別需要注意的地方就是在把block放到集合類當(dāng)中去的時(shí)候脸甘,如果直接把生成的block放入到集合類中恳啥,是無(wú)法在其他地方使用block,必須要對(duì)block進(jìn)行copy丹诀。
[array addObject:[[^{
NSLog(@"hello!");
} copy] autorelease]];
nil钝的,Nil,NULL和NSNull理解
nil
nil 是 ObjC 對(duì)象的字面空值铆遭,對(duì)應(yīng) id 類型的對(duì)象硝桩,或者使用 @interface 聲明的 ObjC 對(duì)象。
例如:
NSString *someString = nil;
NSURL *someURL = nil;
id someObject = nil;
if (anotherObject == nil) // do something
定義:
#ifndef nil
# if __has_feature(cxx_nullptr)
# define nil nullptr
# else
# define nil __DARWIN_NULL
# endif
#endif
// __DARWIN_NULL in _types.h
#define __DARWIN_NULL ((void *)0)
Nil
Nil 是 ObjC 類類型的書(shū)面空值枚荣,對(duì)應(yīng) Class 類型對(duì)象碗脊。
例如:
Class someClass = Nil;
Class anotherClass = [NSString class];
定義聲明和 nil 是差不多的,值相同:
#ifndef Nil
# if __has_feature(cxx_nullptr)
# define Nil nullptr
# else
# define Nil __DARWIN_NULL
# endif
#endif
NULL
NULL 是任意的 C 指針空值橄妆。
例如:
int *pointerToInt = NULL;
char *pointerToChar = NULL;
struct TreeNode *rootNode = NULL;
定義:
// in stddef.h
#define NULL ((void*)0)
NSNull
NSNull 是一個(gè)代表空值的類衙伶,是一個(gè) ObjC 對(duì)象。實(shí)際上它只有一個(gè)單例方法:+[NSNull null]害碾,一般用于表示集合中值為空的對(duì)象矢劲。
例子說(shuō)明:
// 因?yàn)?nil 被用來(lái)用為集合結(jié)束的標(biāo)志,所以 nil 不能存儲(chǔ)在 Foundation 集合里慌随。
NSArray *array = [NSArray arrayWithObjects:@"one", @"two", nil];
// 錯(cuò)誤的使用
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:nil forKey:@"someKey"];
// 正確的使用
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[NSNull null] forKey:@"someKey"];
定義:
NSNull.h
#import <Foundation/NSObject.h>
@interface NSNull : NSObject <NSCopying, NSSecureCoding>
+ (NSNull *)null;
@end
NIL 或 NSNil
ObjC 不存在這兩個(gè)符號(hào)芬沉!
轉(zhuǎn)載參考
iOS基礎(chǔ)面試知識(shí)點(diǎn)總結(jié) - Deft_MKJing的博客 - CSDN博客
nil,Nil阁猜,NULL和NSNull理解(ios)