iOS開(kāi)發(fā)---屬性關(guān)鍵字詳解

iOS開(kāi)發(fā)—屬性關(guān)鍵字詳解

@Property

什么是屬性?

  • 屬性(property)Objective-C的一項(xiàng)特性,用于封裝對(duì)象中的數(shù)據(jù)。這一特性可以令編譯器自動(dòng)編寫(xiě)與屬性相關(guān)的存取方法,并且保存為各種實(shí)例變量。
  • 屬性的本質(zhì)是實(shí)例變量與存取方法的結(jié)合。@property = ivar + getter + setter
    • 實(shí)現(xiàn)流程:
    • 每次增加一個(gè)屬性,系統(tǒng)都會(huì)在 ivar_list中添加一個(gè)成員變量的描述,在method_list 中增加settergetter 方法的描述,在 prop_list中增加一個(gè)屬性的描述,計(jì)算該屬性在對(duì)象中的偏移量,然后給出 settergetter方法對(duì)應(yīng)的實(shí)現(xiàn)。在 setter 方法中從偏移量的位置開(kāi)始賦值,在 getter 方法中從偏移量開(kāi)始取值,為了能夠讀取正確字節(jié)數(shù),系統(tǒng)對(duì)象偏移量的指針類(lèi)型進(jìn)行了類(lèi)型強(qiáng)轉(zhuǎn)。

Property的默認(rèn)設(shè)置

  • 基本數(shù)據(jù)類(lèi)型:atomic, readwrite,assign
  • 對(duì)象類(lèi)型:atomic, readwrite, strong

??:注意:考慮到代碼可讀性以及日常代碼修改頻率,規(guī)范的編碼風(fēng)格中關(guān)鍵詞的順序是:原子性、讀寫(xiě)權(quán)限、內(nèi)存管理語(yǔ)義、getter/getter。

關(guān)鍵字

關(guān)鍵字 解釋
atomic 原子性訪問(wèn)
nonatomic 非原子性訪問(wèn),多線程并發(fā)訪問(wèn)會(huì)提高性能
readwrite 此標(biāo)記說(shuō)明屬性會(huì)被當(dāng)成讀寫(xiě)的,這也是默認(rèn)屬性
readonly 此標(biāo)記說(shuō)明屬性只可以讀,也就是不能設(shè)置,可以獲取
strong 打開(kāi)ARC時(shí)才會(huì)使用,相當(dāng)于retain
weak 打開(kāi)ARC時(shí)才會(huì)使用,相當(dāng)于assign,可以把對(duì)應(yīng)的指針變量置為nil
assign 不會(huì)使引用計(jì)數(shù)加1,也就是直接賦值
unsafe_unretain 與weak類(lèi)似,但是銷(xiāo)毀時(shí)不自動(dòng)清空,容易形成野指針
copy 與strong類(lèi)似,設(shè)置方法會(huì)拷貝一份副本。一般用于修飾字符串和集合類(lèi)的不可變版, block用copy修飾

詳解copy

  • copy語(yǔ)法的作用:

    • 產(chǎn)生副本
      • copy返回的是不可變的副本
      • mutableCopy返回的是可變的副本
    • 修改了副本并不會(huì)影響源對(duì)象,修改了源對(duì)象,并不會(huì)影響副本。
  • copy使用場(chǎng)景:

    • NSString、NSArray、NSictionary 等等經(jīng)常使用copy 關(guān)鍵字,是因?yàn)樗麄冇袑?duì)應(yīng)的可變類(lèi)型:NSMutableString、NSMutableArray、NSMutableDictionary.為確保對(duì)象中的屬性值不會(huì)無(wú)意間變動(dòng),應(yīng)該在設(shè)置新屬性值時(shí)拷貝一份,保護(hù)其封裝性
    • block,也經(jīng)常使用 copy
      • 使用 copy 是從MRC 遺留下來(lái)的“傳統(tǒng)”,在MRC 中,方法內(nèi)部的 block 是在棧區(qū)的,使用 copy 可以把它放到堆區(qū).

      • ARC 中寫(xiě)不寫(xiě)都行:對(duì)于block 使用 copy還是 strong效果是一樣的,但是建議寫(xiě)上 copy,因?yàn)檫@樣顯示告知調(diào)用者“編譯器會(huì)自動(dòng)對(duì) block 進(jìn)行了 copy 操作.

  • 為什么用@property 聲明的NSString(或NSArray,NSDictionary)經(jīng)常使用 copy 關(guān)鍵字,為什么?如果改用strong關(guān)鍵字,可能造成什么問(wèn)題?

    • 因?yàn)楦割?lèi)指針可以指向子類(lèi)對(duì)象,使用 copy 的目的是為了讓本對(duì)象的屬性不受外界影響,使用 copy 無(wú)論給我傳入是一個(gè)可變對(duì)象還是不可對(duì)象,我本身持有的就是一個(gè)不可變的副本. 如果我們使用是 strong,那么這個(gè)屬性就有可能指向一個(gè)可變對(duì)象,如果這個(gè)可變對(duì)象在外部被修改了,那么會(huì)影響該屬性.
  • 如何讓自定義類(lèi)可以用 copy 修飾符?如何重寫(xiě)帶copy 關(guān)鍵字的 setter?

    • 若想令自己所寫(xiě)的對(duì)象具有拷貝功能,則需實(shí)現(xiàn)NSCopying 協(xié)議。如果自定義的對(duì)象分為可變版本與不可變版本,那么就要同時(shí)實(shí)現(xiàn) NSCopyiogNSMutableCopying 協(xié)議,不過(guò)一般沒(méi)什么必要,實(shí)現(xiàn)NSCopying 協(xié)議就夠了
    - (id)copyWithZone:(NSZone *)zone {
        NSObject *copyObj = [[NSObject allocWithZone:zone] init];
        copyObj.name = self.name;
        return copyObj;
    }
    
    - (void)setName;(Mitchell*)name {
        _name = [name copy];
    }
    

atomic與nonatomic

  • 什么是原子性?
    • 并發(fā)編程中確保其操作具備整體性,系統(tǒng)其它部分無(wú)法觀察到中間步驟,只能看到操作前后的結(jié)果
  • atomic:原子性的,編譯器會(huì)通過(guò)鎖定機(jī)制確保settergetter的完整性。
  • nonatomic:非原子性的,不保證settergetter的完整性。
  • 區(qū)別:由于要保證操作完整,atomic速度比較慢,線程相對(duì)安全;nonatomic速度比較快,但是線程不安全。atomic也不是絕對(duì)的線程安全,當(dāng)多個(gè)線程同時(shí)調(diào)用settergetter時(shí),就會(huì)導(dǎo)致獲取的值不一樣。由于鎖定機(jī)制開(kāi)銷(xiāo)較大,一般iOS開(kāi)發(fā)中會(huì)使用nonatomic,而macOS中使用atomic通常不會(huì)有性能瓶頸。
  • 如果對(duì)這塊不太了解,你可以看一下這篇文章atomic到底不安全在哪?

readwrite與readonly

  • 讀寫(xiě)權(quán)限不寫(xiě)時(shí)默認(rèn)為 readwrite 。一般可在 .h 里寫(xiě)成readonly,只對(duì)外提供讀取,在 .m 的Extension中再設(shè)置為 readwrite 可進(jìn)行寫(xiě)入。
//.h文件
@interface MyClass : NSObject
@property (nonatomic, readonly, copy) NSString *name;
@end

//.m文件
@interface MyClass()
@property (nonatomic, readwrite, copy) NSString *name;
@end

比較strong與copy

  • 相同之處:是用于修飾表示擁有關(guān)系的對(duì)象。
  • 不同之處:strong復(fù)制是多個(gè)指針指向同一個(gè)地址,而copy的復(fù)制是每次會(huì)在內(nèi)存中復(fù)制一份對(duì)象,指針指向不同的地址。
    • NSString、NSArray、NSDictionary等不可變對(duì)象用copy修飾,因?yàn)橛锌赡軅魅胍粋€(gè)可變的版本,此時(shí)能保證屬性值不會(huì)受外界影響。
  • 注意??:若用strong修飾NSArray,當(dāng)數(shù)組接收一個(gè)可變數(shù)組,可變數(shù)組若發(fā)生變化,被修飾的屬性數(shù)組也會(huì)發(fā)生變化,也就是說(shuō)屬性值容易被篡改;若用copy修飾NSMutableArray,當(dāng)試圖修改屬性數(shù)組里的值時(shí),程序會(huì)崩潰,因?yàn)閿?shù)組被復(fù)制成了一個(gè)不可變的版本。

比較assign、weak、unsafe_unretain

  • 相同之處:都不是強(qiáng)引用
  • 不同之處:weak引用的 OC 對(duì)象被銷(xiāo)毀時(shí), 指針會(huì)被自動(dòng)清空,不再指向銷(xiāo)毀的對(duì)象,不會(huì)產(chǎn)生野指針錯(cuò)誤unsafe_unretain引用的 OC 對(duì)象被銷(xiāo)毀時(shí), 指針并不會(huì)被自動(dòng)清空, 依然指向銷(xiāo)毀的對(duì)象,很容易產(chǎn)生野指針錯(cuò)誤:EXC_BAD_ACCESSassign修飾基本數(shù)據(jù)類(lèi)型,內(nèi)存在棧上由系統(tǒng)自動(dòng)回收。

@synthesize 和 @dynamic

  • @property 有兩個(gè)對(duì)應(yīng)的詞,一個(gè)是@synthesize,一個(gè)是@dynamic
    如果@synthesize@dynamic 都沒(méi)寫(xiě),那么默認(rèn)的就是
    @syntheszie var = _var;

  • @synthesize 的語(yǔ)義是如果你沒(méi)有手動(dòng)實(shí)現(xiàn) setter 方法和 getter 方法,那么編譯器會(huì)自動(dòng)為你加上這兩個(gè)方法。

  • @dynamic 告訴編譯器:屬性的settergetter 方法由用戶自己實(shí)現(xiàn),不自動(dòng)生成。(當(dāng)然對(duì)于 readonly 的屬性只需提供 getter 即可)
    假如一個(gè)屬性被聲明為

  • @dynamic var;然后你沒(méi)有提供@setter 方法和@getter 方法,編譯的時(shí)候沒(méi)問(wèn)題,但是當(dāng)程序運(yùn)行到 instance.var = someVar,由于缺 setter方法會(huì)導(dǎo)致程序崩潰;
    或者當(dāng)運(yùn)行到 someVar = instance.var 時(shí),由于缺getter 方法同樣會(huì)導(dǎo)致崩潰。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類(lèi)型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,663評(píng)論 1 32
  • 出題者簡(jiǎn)介: 孫源(sunnyxx),目前就職于百度,負(fù)責(zé)百度知道 iOS 客戶端的開(kāi)發(fā)工作,對(duì)技術(shù)喜歡刨根問(wèn)底和...
    戈多_于勒閱讀 1,877評(píng)論 0 5
  • 親和國(guó)學(xué)文創(chuàng)園項(xiàng)目建設(shè)政府協(xié)調(diào)會(huì) 感謝云巖區(qū)委宣傳部文產(chǎn)辦牽頭組織[害羞][抱拳]
    文心訪藝閱讀 179評(píng)論 0 0
  • 幸福就是看家人的臉,不幸就是看人家的臉!
    Ewalnut閱讀 170評(píng)論 0 0
  • 夜,你別太美 我怕留戀。 夜,你別太長(zhǎng) 我怕思念。 夜,你別太黑 我怕孤單。 夜,你別太靜 我怕痛苦。 夜,你別太...
    一碗河撈面閱讀 510評(píng)論 1 2

友情鏈接更多精彩內(nèi)容