1梯码,什么情況使用 weak 關鍵字,相比 assign 有什么不同好啰?
什么情況使用 weak 關鍵字轩娶?
在 ARC 中,在有可能出現(xiàn)循環(huán)引用的時候,往往要通過讓其中一端使用 weak 來解決,比如: delegate 代理屬性
自身已經(jīng)對它進行一次強引用,沒有必要再強引用一次,此時也會使用 weak,自定義 IBOutlet 控件屬性一般也使用 weak;當然框往,也可以使用strong鳄抒。
不同點:
weak此特質(zhì)表明該屬性定義了一種“非擁有關系” (nonowning relationship)。為這種屬性設置新值時椰弊,設置方法既不保留新值许溅,也不釋放舊值。此特質(zhì)同assign類似秉版,然而在屬性所指的對象遭到摧毀時贤重,屬性值也會清空(nil out)。而assign的“設置方法”只會執(zhí)行針對“純量類型” (scalar type沐飘,例如 CGFloat 或 NSlnteger 等)的簡單賦值操作游桩。
assigin 可以用非 OC 對象,而 weak 必須用于 OC 對象牲迫。
2耐朴,怎么用 copy 關鍵字借卧?
用途:
NSString、NSArray筛峭、NSDictionary 等等經(jīng)常使用copy關鍵字铐刘,是因為他們有對應的可變類型:NSMutableString、NSMutableArray影晓、NSMutableDictionary镰吵;
block 也經(jīng)常使用 copy 關鍵字,
block 使用 copy 是從 MRC 遺留下來的“傳統(tǒng)”,在 MRC 中,方法內(nèi)部的 block 是在棧區(qū)的,使用 copy
可以把它放到堆區(qū).在 ARC 中寫不寫都行:對于 block 使用 copy 還是 strong 效果是一樣的挂签,但寫上 copy
也無傷大雅疤祭,還能時刻提醒我們:編譯器自動對 block 進行了 copy 操作。如果不寫 copy
饵婆,該類的調(diào)用者有可能會忘記或者根本不知道“編譯器會自動對 block 進行了 copy
操作”勺馆,他們有可能會在調(diào)用之前自行拷貝屬性值。這種操作多余而低效侨核。你也許會感覺我這種做法有些怪異草穆,不需要寫依然寫。
copy 此特質(zhì)所表達的所屬關系與 strong 類似搓译。然而設置方法并不保留新值悲柱,而是將其“拷貝” (copy)。
當屬性類型為 NSString 時些己,經(jīng)常用此特質(zhì)來保護其封裝性豌鸡,因為傳遞給設置方法的新值有可能指向一個 NSMutableString
類的實例。這個類是 NSString
的子類段标,表示一種可修改其值的字符串涯冠,此時若是不拷貝字符串,那么設置完屬性之后怀樟,字符串的值就可能會在對象不知情的情況下遭人更改功偿。所以,這時就要拷貝
一份“不可變” (immutable)的字符串往堡,確保對象中的字符串值不會無意間變動械荷。只要實現(xiàn)屬性所用的對象是“可變的”
(mutable),就應該在設置新屬性值時拷貝一份虑灰。
用@property聲明 NSString吨瞎、NSArray、NSDictionary 經(jīng)常使用 copy 關鍵字穆咐,是因為他們有對應的可變類型:NSMutableString颤诀、NSMutableArray字旭、NSMutableDictionary,他們之間可能進行賦值操作崖叫,為確保對象中的字符串值不會無意間變動遗淳,應該在設置新屬性值時拷貝一份。
3.@property中有哪些屬性關鍵字心傀?/ @property 后面可以有哪些修飾符屈暗?
屬性可以擁有的特質(zhì)分為四類:
原子性---nonatomic特質(zhì)
在默認情況下,由編譯器合成的方法會通過鎖定機制確保其原子性(atomicity)脂男。如果屬性具備 nonatomic
特質(zhì)养叛,則不使用同步鎖。請注意宰翅,盡管沒有名為“atomic”的特質(zhì)(如果某屬性不具備 nonatomic 特質(zhì)弃甥,那它就是“原子的” (
atomic) ),但是仍然可以在屬性特質(zhì)中寫明這一點汁讼,編譯器不會報錯淆攻。若是自己定義存取方法,那么就應該遵從與屬性特質(zhì)相符的原子性掉缺。
讀/寫權(quán)限---readwrite(讀寫)卜录、readonly (只讀)
內(nèi)存管理語義---assign、strong眶明、weak艰毒、unsafe_unretained、copy
方法名---getter=搜囱、setter=
getter=的樣式:
@property (nonatomic, getter=isOn)BOOLon;
( `setter=`這種不常用丑瞧,也不推薦使用。故不在這里給出寫法蜀肘。)
setter=一般用在特殊的情境下绊汹,比如:
在數(shù)據(jù)反序列化、轉(zhuǎn)模型的過程中扮宠,服務器返回的字段如果以init開頭西乖,所以你需要定義一個init開頭的屬性,但默認生成的setter與getter方法也會以init開頭坛增,而編譯器會把所有以init開頭的方法當成初始化方法获雕,而初始化方法只能返回 self 類型,因此編譯器會報錯收捣。
這時你就可以使用下面的方式來避免編譯器報錯:
@property(nonatomic, strong, getter=p_initBy, setter=setP_initBy:)NSString*initBy;
另外也可以用關鍵字進行特殊說明届案,來避免編譯器報錯:
@property(nonatomic, readwrite, copy, null_resettable)NSString*initBy;- (NSString*)initBy__attribute__((objc_method_family(none)));
不常用的:nonnull,null_resettable,nullable
4. @synthesize和@dynamic分別有什么作用?
1.@property有兩個對應的詞罢艾,一個是 @synthesize楣颠,一個是 @dynamic尽纽。如果 @synthesize和 @dynamic都沒寫,那么默認的就是@syntheszie var = _var;
2.@synthesize 的語義是如果你沒有手動實現(xiàn) setter 方法和 getter 方法童漩,那么編譯器會自動為你加上這兩個方法弄贿。
3.@dynamic 告訴編譯器:屬性的 setter 與 getter 方法由用戶自己實現(xiàn),不自動生成睁冬。(當然對于 readonly 的屬性只需提供 getter 即可)挎春。假如一個屬性被聲明為 @dynamic var看疙,然后你沒有提供 @setter方法和 @getter 方法豆拨,編譯的時候沒問題,但是當程序運行到instance.var = someVar能庆,由于缺 setter 方法會導致程序崩潰施禾;或者當運行到someVar = var時,由于缺 getter 方法同樣會導致崩潰搁胆。編譯時沒問題弥搞,運行時才執(zhí)行相應的方法,這就是所謂的動態(tài)綁定渠旁。
5.用@property聲明的NSString(或NSArray攀例,NSDictionary)經(jīng)常使用copy關鍵字,為什么顾腊?如果改用strong關鍵字粤铭,可能造成什么問題?
1.因為父類指針可以指向子類對象,使用 copy 的目的是為了讓本對象的屬性不受外界影響,使用 copy 無論給我傳入是一個可變對象還是不可對象,我本身持有的就是一個不可變的副本.
2.如果我們使用是 strong ,那么這個屬性就有可能指向一個可變對象,如果這個可變對象在外部被修改了,那么會影響該屬性.
copy 此特質(zhì)所表達的所屬關系與 strong 類似杂靶。然而設置方法并不保留新值梆惯,而是將其“拷貝” (copy)。
當屬性類型為 NSString 時吗垮,經(jīng)常用此特質(zhì)來保護其封裝性垛吗,因為傳遞給設置方法的新值有可能指向一個 NSMutableString
類的實例。這個類是 NSString
的子類烁登,表示一種可修改其值的字符串怯屉,此時若是不拷貝字符串,那么設置完屬性之后饵沧,字符串的值就可能會在對象不知情的情況下遭人更改锨络。所以,這時就要拷貝
一份“不可變” (immutable)的字符串捷泞,確保對象中的字符串值不會無意間變動足删。只要實現(xiàn)屬性所用的對象是“可變的”
(mutable),就應該在設置新屬性值時拷貝一份锁右。
6.IBOutlet連出來的視圖屬性為什么可以被設置成weak?
參考鏈接:Should-iboutlets-be-strong-or-weak-under-arc?
文章告訴我們:
因為既然有外鏈那么視圖在xib或者storyboard中肯定存在失受,視圖已經(jīng)對它有一個強引用了讶泰。
不過這個回答漏了個重要知識,使用storyboard(xib不行)創(chuàng)建的vc拂到,會有一個叫
_topLevelObjectsToKeepAliveFromStoryboard的私有數(shù)組強引用所有top
level的對象痪署,所以這時即便outlet聲明成weak也沒關系