iOS面試之屬性關鍵字(二):常見面試題

Q:ARC下,不顯式指定任何屬性關鍵字時,默認的關鍵字都有哪些劳殖?

對應基本數(shù)據(jù)類型默認關鍵字是:atomic,readwrite,assign
對于普通的 Objective-C 對象:atomic,readwrite,strong

Q:atomic 修飾的屬性是怎么樣保存線程安全的桃犬?

答:編譯器會自動生成互斥鎖,對 setter 和 getter 方法進行加鎖,可以保證屬性的賦值和取值原子性操作是線程安全的,但不包括操作和訪問。
比如說atomic修飾的是一個數(shù)組的話维咸,那么我們對數(shù)組進行賦值和取值是可以保證線程安全的。但是如果我們對數(shù)組進行操作惠爽,比如說給數(shù)組添加對象或者移除對象癌蓖,是不在atomic的負責范圍之內的,所以給被atomic修飾的數(shù)組添加對象或者移除對象是沒辦法保證線程安全的疆股。

Q:什么情況使用 weak 關鍵字费坊,相比 assign 有什么不同?

答:
在 ARC 中旬痹,在有可能出現(xiàn)循環(huán)引用的時候附井,往往要通過讓其中一端使用 weak 來解決讨越,比如: delegate、block永毅。
自身已經(jīng)對它進行一次強引用把跨,沒有必要再強引用一次,此時也會使用 weak沼死,自定義 IBOutlet 控件屬性一般也使用 weak着逐,使用 storyboard(xib 不行)創(chuàng)建的 vc,會有一個叫 _topLevelObjectsToKeepAliveFromStoryboard 的私有數(shù)組強引用所有 top level 的對象意蛀,所以這時即便 outlet 聲明成 weak 也沒關系耸别。當然,也可以使用 strong县钥。
weak 和 assign 的不同點:
① weak只能修飾對象秀姐,而assign既可以修飾對象也可以修飾基本數(shù)據(jù)類型;
② assign修飾的對象在被釋放后若贮,指針仍然指向原對象地址省有;而weak修飾的對象在被釋放之后會自動置指針為 nil;
③ 相同點:在修飾對象的時候谴麦,assign和weak都不改變對象的引用計數(shù)蠢沿。

Q:weak修飾的釋放則自動被置為nil的實現(xiàn)原理

答:weak 實現(xiàn)原理的概括:
Runtime維護了一個weak表,用于存儲指向某個對象的所有weak指針匾效。weak表其實是一個hash(哈希)表舷蟀,Key是所指對象的地址,Value是weak指針的地址(這個地址的值是所指對象的地址)數(shù)組弧轧。

weak 的實現(xiàn)原理可以概括一下三步:

1雪侥、初始化時:runtime會調用objc_initWeak函數(shù)碗殷,初始化一個新的weak指針指向對象的地址精绎。
2、添加引用時:objc_initWeak函數(shù)會調用 objc_storeWeak() 函數(shù)锌妻, objc_storeWeak() 的作用是更新指針指向代乃,創(chuàng)建對應的弱引用表。
3仿粹、釋放時搁吓,調用clearDeallocating函數(shù)。clearDeallocating函數(shù)首先根據(jù)對象地址獲取所有weak指針地址的數(shù)組吭历,然后遍歷這個數(shù)組把其中的數(shù)據(jù)設為nil堕仔,最后把這個entry從weak表中刪除,最后清理對象的記錄晌区。

Q:為什么iOS開發(fā)中摩骨,控件一般為weak而不是strong?

IBOutlet的屬性一般可以設為weak是因為它已經(jīng)被view引用了通贞,除非view被釋放,否則IBOutlet的屬性也不會被釋放恼五,另外IBOutlet屬性的生命周期和view應該是一致的昌罩,所以IBOutlet屬性一般設為weak。
簡單的說灾馒,如果IBOutlet對象是nib/xib scene的擁有者(File’s owner)所持有的對象茎用,那么很顯然擁有者必須“擁有”對象的指針,因此屬性應設置為strong睬罗。而其他的IBOutlet對象的屬性需要設置為weak轨功,因為擁有者并不需要“擁有”他們的指針。

答:因為view被添加到superView上面后容达,就被superView持有了夯辖。我們一般在IB里面的拖的view都是加在了根view或者它的子view上。而根view又被它的controller持有董饰,所以IBOutlet可以用weak蒿褂。如果,在IB里面拖出來的view是一個單獨的view沒有被加到任何其他view上卒暂,則需要用strong啄栓。

Q:以下代碼會出現(xiàn)什么問題?(深淺拷貝)

@property (copy) NSMutableArray *array;
答:
1.把NSMutableArray用copy修飾有時就會crash也祠,因為對這個數(shù)組進行了增刪改操作昙楚,而copy后的數(shù)組變成了不可變數(shù)組NSArray,沒有響應的增刪改方法诈嘿,所以對其進行增刪改操作就會報錯堪旧。
2.默認atomic修飾,編譯器會自動生成互斥鎖奖亚,對 setter 和 getter 方法進行加鎖操作淳梦,這個過程會消耗一些性能,執(zhí)行效率慢,一般使用nonatomic修飾

Q:用@property聲明的NSString(或NSArray昔字,NSDictionary)經(jīng)常使用copy關鍵字爆袍,為什么?如果改用strong關鍵字作郭,可能造成什么問題陨囊?

1.因為父類指針可以指向子類對象,使用 copy 的目的是為了讓本對象的屬性不受外界影響,使用 copy 無論給我傳入是一個可變對象還是不可對象,我本身持有的就是一個不可變的副本.
2.如果我們使用是 strong ,那么這個屬性就有可能指向一個可變對象,如果這個可變對象在外部被修改了,那么會影響該屬性.
copy 此特質所表達的所屬關系與 strong 類似。然而設置方法并不保留新值夹攒,而是將其“拷貝” (copy)蜘醋。

Q:@property 的本質是什么?ivar咏尝、getter压语、setter 是如何生成并添加到這個類中的闲先?

@property的本質是 ivar(實例變量) + getter + setter.

attributes的具體內容包含: 類型, 原子性, 內存語義和對應的實例變量.

我們每次在增加一個屬性, 系統(tǒng)都會在 ivar_list 中添加一個成員變量的描述, 在 method_list 中增加 setter 與 getter 方法的描述, 在屬性列表中增加一個屬性的描述, 然后計算該屬性在對象中的偏移量, 然后給出 setter 與 getter 方法對應的實現(xiàn), 在 setter 方法中從偏移量的位置開始賦值, 在 getter 方法中從偏移量開始取值, 為了能夠讀取正確字節(jié)數(shù), 系統(tǒng)對象偏移量的指針類型進行了類型強轉.

Q:weak屬性需要在dealloc中置nil么?

不需要无蜂。
在ARC環(huán)境無論是強指針還是弱指針都無需在 dealloc 設置為 nil 伺糠, ARC 會自動幫我們處理
即便是編譯器不幫我們做這些,weak也不需要在 dealloc 中置nil:因為在屬性所指的對象遭到摧毀時斥季,屬性值也會清空(nil out)训桶。
當一個被weak修飾的對象被釋放后,weak對象怎么處理的酣倾?
清除weak變量舵揭,同時設置指向為nil。當對象被dealloc釋放后躁锡,在dealloc的內部實現(xiàn)中午绳,會調用弱引用清除的相關函數(shù),會根據(jù)當前對象指針查找弱引用表映之,找到當前對象所對應的弱引用數(shù)組拦焚,將數(shù)組中的所有弱引用指針都置為nil。

Q:說說你理解weak屬性杠输?

Runtime維護了一個weak表赎败,用于存儲指向某個對象的所有weak指針。weak表其實是一個hash(哈希)表蠢甲,Key是所指對象的地址僵刮,Value是weak指針的地址(這個地址的值是所指對象的地址)數(shù)組。
1鹦牛、初始化時:runtime會調用objc_initWeak函數(shù)搞糕,初始化一個新的weak指針指向對象的地址。
2曼追、添加引用時:objc_initWeak函數(shù)會調用 objc_storeWeak() 函數(shù)窍仰, objc_storeWeak() 的作用是更新指針指向,創(chuàng)建對應的弱引用表拉鹃。
3辈赋、釋放時,調用clearDeallocating函數(shù)膏燕。clearDeallocating函數(shù)首先根據(jù)對象地址獲取所有weak指針地址的數(shù)組,然后遍歷這個數(shù)組把其中的數(shù)據(jù)設為nil悟民,最后把這個entry從weak表中刪除坝辫,最后清理對象的記錄。
追問的問題一:
1.實現(xiàn)weak后射亏,為什么對象釋放后會自動為nil近忙?
runtime 對注冊的類竭业, 會進行布局,對于 weak 對象會放入一個 hash 表中及舍。 用 weak 指向的對象內存地址作為 key未辆,當此對象的引用計數(shù)為 0 的時候會 dealloc,假如 weak 指向的對象內存地址是 a 锯玛,那么就會以 a 為鍵咐柜, 在這個 weak 表中搜索,找到所有以 a 為鍵的 weak 對象攘残,從而設置為 nil 拙友。
追問的問題二:
2.當weak引用指向的對象被釋放時,又是如何去處理weak指針的呢歼郭?
1遗契、調用objc_release
2、因為對象的引用計數(shù)為0病曾,所以執(zhí)行dealloc
3牍蜂、在dealloc中,調用了_objc_rootDealloc函數(shù)
4泰涂、在_objc_rootDealloc中捷兰,調用了object_dispose函數(shù)
5、調用objc_destructInstance
6负敏、最后調用objc_clear_deallocating,詳細過程如下:
a. 從weak表中獲取廢棄對象的地址為鍵值的記錄
b. 將包含在記錄中的所有附有 weak修飾符變量的地址贡茅,賦值為 nil
c. 將weak表中該記錄刪除
d. 從引用計數(shù)表中刪除廢棄對象的地址為鍵值的記錄
10.iOS本地數(shù)據(jù)存儲安全
11.BAD_ACCESS的錯誤嗎?你是怎樣調試的其做?
BAD_ACCESS:不管什么時候當你遇到BAD_ACCESS這個錯誤顶考,那就意味著你向一個已經(jīng)釋放的對象發(fā)送消息。
BAD_ACCESS的本質:
在C和OC中妖泄,你一直在處理指針驹沿,指針無非是存儲另一個變量的內存地址的變量。當向一個對象發(fā)送消息時蹈胡,指向該對象的指針將會被引用渊季,這意味著,你獲取了指針所指的內存地址罚渐,并訪問該存儲區(qū)域的值却汉。
當該存儲器區(qū)域不再映射到你的應用時,或者換句話說荷并,該內存區(qū)域在你認為使用的時候沒有使用合砂,該內存區(qū)域是無法訪問的,這時內核會拋出一個異常(EXC)源织,表明你的應用程序不能訪問該存儲器區(qū)域(BAD_ACCESS).
當你碰到BAD_ACCESS翩伪,這意味著你試圖發(fā)送消息到的內存塊微猖,但內存塊無法執(zhí)行該消息。但是缘屹,在某些情況下凛剥,BAD_ACCESS是由被損壞的指針引起的,每當你的應用程序嘗試引用損壞的指針轻姿,一個異常就會被內核拋出犁珠。

Q:@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 方法同樣會導致崩潰独榴。

///////////////////

@property有兩個關鍵詞, @synthesize(默認值)和@dynamic.
@synthesize表示系統(tǒng)會默認添加一個@syntheszie var = _var的實例變量, 并且自動生成setter和getter方法. @synthesize 合成實例變量有以下幾點規(guī)則:
如果指定了成員變量的名稱, 會生成一個指定的名稱的成員變量.
如果這個成員已經(jīng)存在就不再生成了.
如果沒有指定成員變量的名稱會自動生成一個屬性同名的成員變量.
@synthesize的使用場景:
同時重寫了setter和getter時
重寫了只讀屬性的getter時
在使用了@dynamic時
在@Protocol和category中定義屬性時
重載父類的屬性時, 來手動合成Ivar(實例變量/成員變量).
@dynamic表示我們不需要系統(tǒng)自動生成, 由用戶自己實現(xiàn), 如果沒有手動生成的話, 在使用過程中是會奔潰的.

Q:@synthesize合成實例變量的規(guī)則是什么僧叉?假如property名為foo,存在一個名為_foo的實例變量棺榔,那么還會自動合成新變量么瓶堕?

總結下 @synthesize 合成實例變量的規(guī)則,有以下幾點:
如果指定了成員變量的名稱,會生成一個指定的名稱的成員變量,
如果這個成員已經(jīng)存在了就不再生成了.
如果是 @synthesize foo; 還會生成一個名稱為foo的成員變量症歇,也就是說:
如果沒有指定成員變量的名稱會自動生成一個屬性同名的成員變量,
如果是 @synthesize foo = _foo; 就不會生成成員變量了.
假如 property 名為 foo郎笆,存在一個名為 _foo 的實例變量,那么還會自動合成新變量么忘晤?
不會宛蚓。

Q:在有了自動合成屬性實例變量之后,@synthesize還有哪些使用場景德频?

什么情況下不會autosynthesis(自動合成)苍息?
同時重寫了 setter 和 getter 時
重寫了只讀屬性的 getter 時
使用了 @dynamic 時
在 @protocol 中定義的所有屬性
在 category 中定義的所有屬性
重載的屬性
當你在子類中重載了父類中的屬性,你必須 使用 @synthesize 來手動合成ivar壹置。

@synthesize 語法還有一個應用場景竞思,但是不太建議大家使用:
可以在類的實現(xiàn)代碼里通過 @synthesize 語法來指定實例變量的名字

@implementation CYLPerson
@synthesize firstName = _myFirstName;
@synthesize lastName = _myLastName;
@end

可變數(shù)組&不可變數(shù)組修飾符的使用結論:

當修飾可變類型的屬性時,如NSMutableArray钞护、NSMutableDictionary盖喷、NSMutableString,用strong难咕。
當修飾不可變類型的屬性時课梳,如NSArray、NSDictionary余佃、NSString暮刃,用copy。

深拷貝與淺拷貝

淺拷貝就是拷貝之后爆土,并沒有真正的復制椭懊,而是復制對象和原對象都指向同一個地址
深拷貝是真正的復制了一份,復制的對象只想新的地址;
copy:對于可變對象為深拷貝步势,對于不可變對象為淺拷貝;
mutablecopy:始終為深拷貝;
淺拷貝簡單點說就是對內存地址的復制氧猬,讓目標對象指針和源對象指針指向同一片內存空間;
深拷貝: 內容拷貝,會創(chuàng)建一個新的對象坏瘩。深拷貝就是拷貝地址中的內容盅抚,讓目標對象產生新的內存區(qū)域,且將源內存區(qū)域中的內容復制到目標內存區(qū)域中;

Q:objc中的類方法和實例方法有什么本質區(qū)別和聯(lián)系倔矾?

(實例變量 = 成員變量 = ivar)
類方法:
1. 類方法是屬于類對象的
2. 類方法只能通過類對象調用
3. 類方法中的self是類對象
4. 類方法可以調用其他的類方法
5. 類方法中不能訪問成員變量
6. 類方法中不定直接調用對象方法
實例方法:
1. 實例方法是屬于實例對象的
2. 實例方法只能通過實例對象調用
3. 實例方法中的self是實例對象
4. 實例方法中可以訪問成員變量
5. 實例方法中直接調用實例方法
6. 實例方法中也可以調用類方法(通過類名)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末妄均,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子哪自,更是在濱河造成了極大的恐慌丰包,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件提陶,死亡現(xiàn)場離奇詭異烫沙,居然都是意外死亡,警方通過查閱死者的電腦和手機隙笆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門锌蓄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人撑柔,你說我怎么就攤上這事瘸爽。” “怎么了铅忿?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵剪决,是天一觀的道長。 經(jīng)常有香客問我,道長柑潦,這世上最難降的妖魔是什么享言? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮渗鬼,結果婚禮上览露,老公的妹妹穿的比我還像新娘。我一直安慰自己譬胎,他們只是感情好差牛,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著堰乔,像睡著了一般偏化。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上镐侯,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天侦讨,我揣著相機與錄音,去河邊找鬼析孽。 笑死搭伤,一個胖子當著我的面吹牛,可吹牛的內容都是我干的袜瞬。 我是一名探鬼主播怜俐,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼邓尤!你這毒婦竟也來了拍鲤?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤汞扎,失蹤者是張志新(化名)和其女友劉穎季稳,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體澈魄,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡景鼠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了痹扇。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铛漓。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鲫构,靈堂內的尸體忽然破棺而出浓恶,到底是詐尸還是另有隱情,我是刑警寧澤结笨,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布包晰,位于F島的核電站湿镀,受9級特大地震影響,放射性物質發(fā)生泄漏伐憾。R本人自食惡果不足惜勉痴,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望塞耕。 院中可真熱鬧蚀腿,春花似錦嘴瓤、人聲如沸扫外。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽筛谚。三九已至,卻和暖如春停忿,著一層夾襖步出監(jiān)牢的瞬間驾讲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工席赂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吮铭,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓颅停,卻偏偏與公主長得像谓晌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子癞揉,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354