iOS經典面試題總結
▲點擊上方「CocoaChina」關注即可免費學習 iOS 開發
本文為投稿文章,作者:jingxianli0922
我根據自己的情況做了一下總結,答案是我總結的,如有答的不好的地方,希望批評指正以及交流,謝謝!
內存管理
1.什麼是ARC?
ARC是automatic reference counting自動引用計數,在程序編譯時自動加入retain/release。在對象被創建時retain count 1,在對象被release時count-1,當count=0時,銷毀對象。程序中加入autoreleasepool對象會由系統自動加上autorelease方法,如果該對象引用計數為0,則銷毀。那麼ARC是為了解決MRC手動管理內存存在的一些而誕生的。
MRC下內存管理的缺點:
釋放一個堆內存時,首先要確定指向這個堆空間的指針都被release了。(避免提前釋放)
釋放指針指向的堆空間,首先要確定哪些指向同一個堆,這些指針只能釋放一次。(避免釋放多次,造成內存泄露)
模塊化操作時,對象可能被多個模塊創建和使用,不能確定最後由誰釋放
多線程操作時,不確定哪個線程最後使用完畢。
雖然ARC給我們編程帶來的很多好多,但也可能出現內存泄露。如下面兩種情況:
循環參照:A有個屬性參照B,B有個屬性參照A,如果都是strong參照的話,兩個對象都無法釋放。
死循環:如果有個ViewController中有無限循環,也會導致即使ViewController對應的view消失了,ViewController也不能釋放。
2.block一般用那個關鍵字修飾,為什麼?
block一般使用copy關鍵之進行修飾,block使用copy是從MRC遺留下來的「傳統」,在MRC中,方法內容的block是在棧區的,使用copy可以把它放到堆區。但在ARC中寫不寫都行:編譯器自動對block進行了copy操作。
3.用@property聲明的NSString(或NSArray,NSDictionary)經常使用copy關鍵字,為什麼?如果改用strong關鍵字,可能造成什麼問題?
答:用@property聲明 NSString、NSArray、NSDictionary 經常使用copy關鍵字,是因為他們有對應的可變類型:NSMutableString、NSMutableArray、NSMutableDictionary,他們之間可能進行賦值操作,為確保對象中的字元串值不會無意間變動,應該在設置新屬性值時拷貝一份。
如果我們使用是strong,那麼這個屬性就有可能指向一個可變對象,如果這個可變對象在外部被修改了,那麼會影響該屬性。
copy此特質所表達的所屬關係與strong類似。然而設置方法並不保留新值,而是將其「拷貝」 (copy)。 當屬性類型為NSString時,經常用此特質來保護其封裝性,因為傳遞給設置方法的新值有可能指向一個NSMutableString類的實例。這個類是NSString的子類,表示一種可修改其值的字元串,此時若是不拷貝字元串,那麼設置完屬性之後,字元串的值就可能會在對象不知情的情況下遭人更改。所以,這時就要拷貝一份「不可變」 (immutable)的字元串,確保對象中的字元串值不會無意間變動。只要實現屬性所用的對象是「可變的」 (mutable),就應該在設置新屬性值時拷貝一份。
4.runloop、autorelease pool以及線程之間的關係。
每個線程(包含主線程)都有一個Runloop。對於每一個Runloop,系統會隱式創建一個Autorelease pool,這樣所有的release pool會構成一個像callstack一樣的一個棧式結構,在每一個Runloop結束時,當前棧頂的Autorelease pool會被銷毀,這樣這個pool里的每個Object會被release。
5.@property 的本質是什麼?ivar、getter、setter 是如何生成並添加到這個類中的。
「屬性」(property)有兩大概念:ivar(實例變數)、存取方法(access method=getter),即@property = ivar getter setter。
例如下面的這個類:
@interfaceWBTextView:UITextView
@property(nonatomic,copy)NSString*placehold;
@property(nonatomic,copy)UIColor*placeholdColor;
@end
類完成屬性的定以後,編譯器會自動編寫訪問這些屬性的方法(自動合成autosynthesis),上述代碼寫出來的類等效與下面的代碼:
@interfaceWBTextView:UITextView
-(NSString*)placehold;
-(void)setPlacehold:(NSString*)placehold;
-(UIColor*)placeholdColor;
-(void)setPlaceholdColor:(UIColor*)placeholdColor;
@end
詳細介紹見:http://blog.csdn.net/jasonjwl/article/details/49427377
6.分別寫一個setter方法用於完成@property (nonatomic,retain)NSString *name和@property (nonatomic,copy) NSString *name
retain屬性的setter方法是保留新值並釋放舊值,然後更新實例變數,令其指向新值。順序很重要。假如還未保留新值就先把舊值釋放了,而且兩個值又指向同一個對象,先執行的release操作就可能導致系統將此對象永久回收。
-(void)setName:(NSString*)name
{
[nameretain];
[_namerelease];
_name=name;
}
-(void)setName:(NSString*)name
{
[_namerelease];
_name=[namecopy];
}
7.說說assign vs weak,_block vs _weak的區別
assign適用於基本數據類型,weak是適用於NSObject對象,並且是一個弱引用。
assign其實頁可以用來修飾對象,那麼為什麼不用它呢?因為被assign修飾的對象在釋放之後,指針的地址還是存在的,也就是說指針並沒有被置為nil。如果在後續內存分配中,剛才分到了這塊地址,程序就會崩潰掉。而weak修飾的對象在釋放之後,指針地址會被置為nil。
_block是用來修飾一個變數,這個變數就可以在block中被修改。
_block:使用_block修飾的變數在block代碼塊中會被retain(ARC下,MRC下不會retain)
_weak:使用_weak修飾的變數不會在block代碼塊中被retain
8.請說出下面代碼是否有問題,如果有問題請修改?
@autoreleasepool{
for
(inti=0;i[largeNumber;i ){(因識別問題,該行代碼中尖括弧改為方括弧代替)
Person*per=[[Personalloc]init];
[perautorelease];
}
}
內存管理的原則:如果對一個對象使用了alloc、copy、retain,那麼你必須使用相應的release或者autorelease。咋一看,這道題目有alloc,也有autorelease,兩者對應起來,應該沒問題。但autorelease雖然會使引用計數減一,但是它並不是立即減一,它的本質功能只是把對象放到離他最近的自動釋放池裡。當自動釋放池銷毀了,才會向自動釋放池中的每一個對象發送release消息。這道題的問題就在autorelease。因為largeNumber是一個很大的數,autorelease又不能使引用計數立即減一,所以在循環結束前會造成內存溢出的問題。
解決方案如下:
@autoreleasepool{
for
(inti=0;i[100000;i ){(因識別問題,該行代碼中尖括弧改為方括弧代替)
@autoreleasepool{
Person*per=[[Personalloc]init];
[perautorelease];
}
}
}
在循環內部再加一個自動釋放池,這樣就能保證每創建一個對象就能及時釋放。
9.請問下面代碼是否有問題,如有問題請修改?
@autoreleasepool{
NSString*str=[[NSStringalloc]init];
[strretain];
[strretain];
str=@
"jxl"
;
[strrelease];
[strrelease];
[strrelease];
}
這道題跟第8題一樣存在內存泄露問題,1.內存泄露 2.指向常量區的對象不能release。
指針變數str原本指向一塊開闢的堆區空間,但是經過重新給str賦值,str的指向發生了變化,由原來指向堆區空間,到指向常量區。常量區的變數根本不需要釋放,這就導致了原來開闢的堆區空間沒有釋放,照成內存泄露。
10.什麼情況下使用weak關鍵字,相比assign有什麼不同?什麼情況使用weak關鍵字?
在ARC中,在有可能出現循環引用的時候,往往要通過讓其中一端使用weak來解決。比如delegate代理
自身已經對它進行一次強引用,沒有必要再強引用一次,此時也會使用weak,自定義控制項屬性一般也使用weak。
不同點:
weak此特質表明該屬性定義了一種「非擁有關係」。為這種屬性設置新值時,設置方法既不保留新值,也不釋放舊值。此特性與assign一樣,然而在屬性所指的對象遭到推毀時,屬性值也會清空。而assign的「設置方法」只會執行針對「純量類型」 (scalar type,例如 CGFloat 或 NSlnteger 等)的簡單賦值操作。
assign可以用非OC對象,而weak必須用於OC對象。
11.內存管理語義(assign、strong、weak等的區別)
assign 「設置方法」 只會執行針對「純量」的簡單賦值操作。
strong 此特質表明該屬性定義了一種「擁有關係」。為這種屬性設置新值時,設置方法會先保留新值,並釋放舊值,然後再將新值設置上去。
weak 此特質表明該屬性定義了一種「非擁有關係」。為這種屬性設置新值時,設置方法既不保留新值,也不釋放舊值。此特質同assign類似,然而在屬性所指的對象遭到推毀時,屬性值也會清空。
unsafe_unretained 此特質的語義和assign相同,但是它適用於「對象類型」,該特質表達一種「非擁有關係」,當目標對象遭到推毀時,屬性值不會自動清空,這一點與weak有區別。
copy 此特質所表達的所屬關係與strong類似。然而設置方法並不保留新值,而是設置方法並不保留新值,而是將其「拷貝」。當屬性類型為NSString*時,經常用此特質來保護其封裝性,因為傳遞給設置方法的新值有可能指向一個NSMutableString類的實例。這個類是NSString的子類,表示一種可以修改其值的字元串,此時若是不拷貝字元串,那麼設置完屬性之後,字元串的值就可能會在對象不知情的情況下遭人更改。所以,這時就要拷貝一份「不可變」的字元串,確保對象中的字元串值不會無意間變動。只要實現屬性所用的對象是「可變的」,就應該在設置新屬性值時拷貝一份。
後續會繼續增加內存管理方面的內容以及多線程等內容,持續更新中....,敬請期待!
參考:
招聘一個靠譜的iOS
《招聘一個靠譜的iOS》面試題參考答案(上)
Matt Galloway 《Effective Objective-C 2.0》
微信號:CocoaChinabbs
▲長按二維碼「識別」關注即可免費學習 iOS 開發
月薪十萬、出任CEO、贏娶白富美、走上人生巔峰不是夢
--------------------------------------
商務合作QQ:645047738
投稿郵箱:support@cocoachina.com
推薦閱讀:
※與食管癌相關的LncRNA:食管癌的LncRNA調控機制總結
※Soffe 書啡總結|百變陰晴不變天
※校驗期執業總結
※心理診斷技能總結
※我的總結