OC中,任何屬性都有3種特性,分別是
1.多線程特性
2.讀/寫特性
3.內存管理特性
多線程特性
多線程特性有nonatomic和atomic兩種,分別表示非原子性和原子性。默認使用atomic,提供線程安全保護。但我們一般設置為nonatomic。
讀寫特性
讀寫特性有readwrite和readonly兩種,默認使用readwrite,使用readwrite編譯器會生成存取方法,如果只使用readonly方法,則只會生成取方法。
內存管理特性
內存管理特性相對復雜,有strong、retain、weak、copy、unsafe_unretained、assign集中形式。
OC對象屬性可使用strong、retain、weak、copy,默認值為strong
其中strong與retain等價,表示強引用,正常情況下使用這個特性;
weak表示弱引用,當兩個對象是父子關系,且子對象持有對父對象的引用時,該引用需要聲明為weak,否則會導致引用循環;
copy表示返回對象的副本,擁有可變子類的對象需要用該特性聲明,如NSArray,NSDictionary,NSData,NSString,但它們的可變子類仍使用strong
非對象屬性可使用unsafe_unretained、assign
,默認值為unsafe_unretained,兩者等價
參考
被無數人寫過的assign,retain,strong,weak,unsafe_unretained,還有copy
iOS中代理屬性為什么要用Weak修飾?
常見問題
什么情況使用 weak 關鍵字?相比 assign 有什么不同?
1.在ARC中,有可能出現引用循環的,使用weak。如delegate作為屬性時,需要聲明為weak。
2.自身已經進行了強引用,沒必要再使用強引用,不過使用強引用也沒有問題,如使用storyboard創建的viewController,那么會有一個叫 _topLevelObjectsToKeepAliveFromStoryboard的私有數組強引用所有top level的對象,同時top level對象強引用所有子對象,那么vc沒必要再強引用top level對象的子對象。
不同點:
1.使用范圍:一般assign用于簡單數據類型,在非ARC時代,它是屬性的默認值,在ARC時代,一般使用unsafe_unretained,而weak則必須用于OC對象。
2.對象釋放的表現:當weak指向的對象被釋放時,屬性值會置空,而assign則不會,這時使用該屬性訪問對象可能會導致程序崩潰。
怎么用 copy 關鍵字?(什么時候使用Copy)
1.NSString、NSArray、NSDictionary,NSData 等等經常使用copy關鍵字,是因為他們有對應的可變類型:NSMutableString、NSMutableArray、NSMutableDictionary,NSMutableDate;他們之間可能進行賦值操作,為確保對象中的字符串值不會無意間變動,應該在設置新屬性值時拷貝一份。
2.block使用copy,block 使用 copy 是從 MRC 遺留下來的“傳統”,在 MRC 中,方法內部的 block 是在棧區的,使用 copy 可以把它放到堆區.在 ARC 中寫不寫都行:對于 block 使用 copy 還是 strong 效果是一樣的,但寫上 copy 也無傷大雅,還能時刻提醒我們:編譯器自動對 block 進行了 copy 操作。如果不寫 copy ,該類的調用者有可能會忘記或者根本不知道“編譯器會自動對 block 進行了 copy 操作”,他們有可能會在調用之前自行拷貝屬性值。這種操作多余而低效。
這個寫法會出什么問題: @property (copy) NSMutableArray *array;
兩個問題
1.使用copy,那么array的實際類型為NSArray,在調用NSMutableArray專有的方法,如[array removeObjectAtIndex:0];時程序會崩潰;
2.沒有指明多線程特性,默認使用的是atomic,影響性能。
如何讓自己的類用 copy 修飾符?如何重寫帶 copy 關鍵字的 setter?
若想令自己所寫的對象具有拷貝功能,則需實現 NSCopying 協議。如果自定義的對象分為可變版本與不可變版本,那么就要同時實現
NSCopying
與NSMutableCopying
協議。如下
- (void)setName:(NSString *)name {
//[_name release];
_name = [name copy];
}
@property 的本質是什么?ivar、getter、setter 是如何生成并添加到這個類中的
1.@property = ivar + getter + setter
2.自動合成,完成屬性定義后,編譯器會自動編寫訪問這些屬性所需的方法,此過程叫做“自動合成”(autosynthesis)。需要強調的是,這個過程由編譯器在編譯期執行。默認為@synthesize firstName = _myFirstName;
@property中有哪些屬性關鍵字?/ @property 后面可以有哪些修飾符?
任何屬性都有3種特性,分別是
1.多線程特性
2.讀/寫特性
3.內存管理特性
1)多線程特性
nonatomic和atomic,默認使用atomic,但我們一般設置為nonatomic。
2)讀寫特性
readwrite和readonly,默認使用readwrite,使用readwrite編譯器會生成存取方法,如果只使用readonly方法,則只會生成取方法。
3)內存管理特性
strong、retain
weak
copy
unsafe_unretained、assign
OC對象屬性可使用strong、retain、weak、copy,默認值為strong
其中strong與retain等價,強引用,正常情況下使用這個
weak表示弱引用,當出現父子關系而子又需要有指向父的指針時使用
copy表示返回對象的副本,擁有可變子類時使用,如NSArray,NSDictionary,NSData,NSString,但它們的可變子類仍使用strong
非對象屬性可使用unsafe_unretained、assign
,默認值為unsafe_unretained,兩者等價
block使用copy修飾
delegate使用weak修飾
被無數人寫過的assign,retain,strong,weak,unsafe_unretained,還有copy
iOS中代理屬性為什么要用Weak修飾?
weak屬性需要在dealloc中置nil么?
不需要
1.在ARC環境無論是強指針還是弱指針都無需在 dealloc 設置為 nil , ARC 會自動幫我們處理
2.非arc中,weak屬性指向的對象遭到摧毀時,屬性值也會清空(nil out)。
@synthesize和@dynamic分別有什么作用?
@property有兩個對應的詞,一個是 @synthesize,一個是 @dynamic。如果 @synthesize和 @dynamic都沒寫,那么默認的就是@syntheszie var = _var;
- @synthesize 的語義是如果你沒有手動實現 setter 方法和 getter 方法,那么編譯器會自動為你加上這兩個方法。
- @dynamic 告訴編譯器:屬性的 setter 與 getter 方法由用戶自己實現,不自動生成。(當然對于 readonly 的屬性只需提供 getter 即可)。假如一個屬性被聲明為 @dynamic var,然后你沒有提供 @setter方法和 @getter 方法,編譯的時候沒問題,但是當程序運行到
instance.var = someVar
,由于缺 setter 方法會導致程序崩潰;或者當運行到someVar = var
時,由于缺 getter 方法同樣會導致崩潰。編譯時沒問題,運行時才執行相應的方法,這就是所謂的動態綁定。
ARC下,不顯式指定任何屬性關鍵字時,默認的關鍵字都有哪些?
- 對應基本數據類型默認關鍵字是
atomic,readwrite,assign
- 對于普通的 Objective-C 對象
atomic,readwrite,strong
用@property聲明的NSString(或NSArray,NSDictionary)經常使用copy關鍵字,為什么?如果改用strong關鍵字,可能造成什么問題?
使用strong,如果給該屬性賦值時,賦值的類型是可變類型,則外部的修改會影響到該屬性的值,使用copy相當于建立一個備份,不會影響。
@property (nonatomic ,readwrite, strong) NSArray *array;
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
NSArray *array = @[ @1, @2, @3, @4 ];
self.array = mutableArray;
[mutableArray removeAllObjects];;
NSLog(@"%@",self.array);
打印結果為空。
@synthesize合成實例變量的規則是什么?假如property名為foo,存在一個名為_foo
的實例變量,那么還會自動合成新變量么?
1)合成規則如下:
- 如果指定了成員變量的名稱,但該成員變量沒有聲明,會生成一個指定的名稱的成員變量,如果已經聲明,則該屬性對應操作該成員變量
- 如果不指定成員變量的名稱,則會生成一個與屬性同名的成員變量。例如,
@synthesize foo;
還會生成一個名稱為foo的成員變量 - 不寫@synthesize時,編譯器默認生成 @synthesize foo = _foo;
2)此情況等同于以下情況
@property (copy,nonatomic) NSString foo;
@synthesize foo = _foo;
根據合成規則第一條,不會再生成新變量。