原文出自:http://mobile.51cto.com/iphone-402619.htmjava
一、Object-C有多繼承嗎?沒有的話用什麼代替?cocoa 中全部的類都是NSObject 的子類 ios
多繼承在這裏是用protocol 委託代理 來實現的c++
你不用去考慮繁瑣的多繼承 ,虛基類的概念.程序員
ood的多態特性 在 obj-c 中經過委託來實現.面試
二、Object-C有私有方法嗎?私有變量呢? objective-c
objective-c – 類裏面的方法只有兩種, 靜態方法和實例方法. 這彷佛就不是完整的面向對象了,按照OO的原則就是一個對象只暴露有用的東西. 若是沒有了私有方法的話, 對於一些小範圍的代碼重用就不那麼順手了. 在類裏面聲名一個私有方法編程
@interface Controller : NSObject { NSString *something; }設計模式
+ (void)thisIsAStaticMethod;數組
– (void)thisIsAnInstanceMethod;緩存
@end
@interface Controller (private) -
(void)thisIsAPrivateMethod;
@end
@private能夠用來修飾私有變量
在Objective‐C中,全部實例變量默認都是私有的,全部實例方法默認都是公有的
三、關鍵字const什麼含義?
const意味着」只讀」,下面的聲明都是什麼意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前兩個的做用是同樣,a是一個常整型數。第三個意味着a是一個指向常整型數的指針(也就是,整型數是不可修改的,但指針能夠)。第四個意思a是一個指向整 型數的常指針(也就是說,指針指向的整型數是能夠修改的,但指針是不可修改的)。最後一個意味着a是一個指向常整型數的常指針(也就是說,指針指向的整型 數是不可修改的,同時指針也是不可修改的)。
結論:
•; 關鍵字const的做用是爲給讀你代碼的人傳達很是有用的信息,實際上,聲明一個參數爲常量是爲了告訴了用戶這個參數的應用目的。若是你曾花不少時間清理其它人留下的垃圾,你就會很快學會感謝這點多餘的信息。(固然,懂得用const的程序員不多會留下的垃圾讓別人來清理的。)
•; 經過給優化器一些附加的信息,使用關鍵字const也許能產生更緊湊的代碼。
•; 合理地使用關鍵字const能夠使編譯器很天然地保護那些不但願被改變的參數,防止其被無心的代碼修改。簡而言之,這樣能夠減小bug的出現。
欲阻止一個變量被改變,能夠使用 const 關鍵字。在定義該 const 變量時,一般須要對它進行初
始化,由於之後就沒有機會再去改變它了;
(2)對指針來講,能夠指定指針自己爲 const,也能夠指定指針所指的數據爲 const,或兩者同時指定爲 const;
(3)在一個函數聲明中,const 能夠修飾形參,代表它是一個輸入參數,在函數內部不能改變其值;
(4)對於類的成員函數,若指定其爲 const 類型,則代表其是一個常函數,不能修改類的成員變量;
(5)對於類的成員函數,有時候必須指定其返回值爲 const 類型,以使得其返回值不爲「左值」。
四、關鍵字volatile有什麼含義?並給出三個不一樣例子?
一個定義爲volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到
這個變量時必須每次都當心地從新讀取這個變量的值,而不是使用保存在寄存器裏的備份。下面是volatile變量的幾個例子:
並行設備的硬件寄存器(如:狀態寄存器)
一箇中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)
多線程應用中被幾個任務共享的變量
一個參數既能夠是const還能夠是volatile嗎?解釋爲何。
一個指針能夠是volatile 嗎?解釋爲何。
下面是答案:
是的。一個例子是隻讀的狀態寄存器。它是volatile由於它可能被意想不到地改變。它是const由於程序不該該試圖去修改它。
是的。儘管這並不很常見。一個例子是當一箇中服務子程序修該一個指向一個buffer的指針時。
static做用?
函數體內 static 變量的做用範圍爲該函數體,不一樣於 auto 變量,該變量的內存只被分配一次,
所以其值在下次調用時仍維持上次的值;
(2)在模塊內的 static 全局變量能夠被模塊內所用函數訪問,但不能被模塊外其它函數訪問;
(3)在模塊內的 static 函數只可被這一模塊內的其它函數調用,這個函數的使用範圍被限制在聲明
它的模塊內;
(4)在類中的 static 成員變量屬於整個類所擁有,對類的全部對象只有一份拷貝;
(5)在類中的 static 成員函數屬於整個類所擁有,這個函數不接收 this 指針,於是只能訪問類的static 成員變量。
六、#import和#include的區別,@class表明什麼?
@class通常用於頭文件中須要聲明該類的某個實例變量的時候用到,在m文件中仍是須要使用#import
而#import比起#include的好處就是不會引發重複包含
七、線程和進程的區別?
進程和線程都是由操做系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的併發性。
進程和線程的主要差異在於它們是不一樣的操做系統資源管理方式。進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一 個進程中的不一樣執行路徑。線程有本身的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,因此多進程的程序要比多線程的程 序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行而且又要共享某些變量的併發操做,只能用線程,不能用進程。
八、堆和棧的區別?
管理方式:對於棧來說,是由編譯器自動管理,無需咱們手工控制;對於堆來講,釋放工做由程序員控制,容易產生memory leak。
申請大小:
棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在 WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就肯定的常數),若是申請的空間超過棧的剩餘空間時,將提示overflow。因 此,能從棧得到的空間較小。
堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是因爲系統是用鏈表來存儲的空閒內存地址的,天然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。因而可知,堆得到的空間比較靈活,也比較大。
碎片問題:對於堆來說,頻繁的new/delete勢必會形成內存空間的不連續,從而形成大量的碎片,使程序效率下降。對於棧來說,則不會存在這個問題,由於棧是先進後出的隊列,他們是如此的一一對應,以致於永遠都不可能有一個內存塊從棧中間彈出
分配方式:堆都是動態分配的,沒有靜態分配的堆。棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,好比局部變量的分配。動態分配由alloca函數進行分配,可是棧的動態分配和堆是不一樣的,他的動態分配是由編譯器進行釋放,無需咱們手工實現。
分配效率:棧是機器系統提供的數據結構,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高。堆則是C/C++函數庫提供的,它的機制是很複雜的。
九、Object-C的內存管理?
1.當你使用new,alloc和copy方法建立一個對象時,該對象的保留計數器值爲1.當你再也不使用該對象時,你要負責向該對象發送一條release或autorelease消息.這樣,該對象將在使用壽命結束時被銷燬.
2.當你經過任何其餘方法得到一個對象時,則假設該對象的保留計數器值爲1,並且已經被設置爲自動釋放,你不須要執行任何操做來確保該對象被清理.若是你打算在一段時間內擁有該對象,則須要保留它並確保在操做完成時釋放它.
3.若是你保留了某個對象,你須要(最終)釋放或自動釋放該對象.必須保持retain方法和release方法的使用次數相等.
十、爲何不少內置的類,如TableViewController的delegate的屬性是assign不是retain?
循環引用
全部的引用計數系統,都存在循環應用的問題。例以下面的引用關係:
對象a建立並引用到了對象b.
對象b建立並引用到了對象c.
對象c建立並引用到了對象b.
這時候b和c的引用計數分別是2和1。當a再也不使用b,調用release釋放對b的全部權,由於c還引用了b,因此b的引用計數爲1,b不會被釋放。b不釋放,c的引用計數就是1,c也不會被釋放。今後,b和c永遠留在內存中。
這種狀況,必須打斷循環引用,經過其餘規則來維護引用關係。好比,咱們常見的delegate每每是assign方式的屬性而不是retain方式的屬 性,賦值不會增長引用計數,就是爲了防止delegation兩端產生沒必要要的循環引用。若是一個UITableViewController 對象a通 過retain獲取了UITableView對象b的全部權,這個UITableView對象b的delegate又是a,若是這個delegate是 retain方式的,那基本上就沒有機會釋放這兩個對象了。本身在設計使用delegate模式時,也要注意這點。
十一、定義屬性時,什麼狀況使用copy、assign、retain?
assign用於簡單數據類型,如NSInteger,double,bool,
retain和copy用於對象,
copy用於當a指向一個對象,b也想指向一樣的對象的時候,若是用assign,a若是釋放,再調用b會crash,若是用copy 的方式,a和b各自有本身的內存,就能夠解決這個問題。
retain 會使計數器加一,也能夠解決assign的問題。
另外:atomic和nonatomic用來決定編譯器生成的getter和setter是否爲原子操做。在多線程環境下,原子操做是必要的,不然有可能引發錯誤的結果。
加了atomic,setter函數會變成下面這樣:
if (property != newValue) {
[property release];
property = [newValue retain];
}
十二、對象是何時被release的?
引用計數爲0時。
autorelease實際上只是把對release的調用延遲了,對於每個Autorelease,系統只是把該Object放入了當前的 Autorelease pool中,當該pool被釋放時,該pool中的全部Object會被調用Release。對於每個Runloop,系統會 隱式建立一個Autorelease pool,這樣全部的release pool會構成一個象CallStack同樣的一個棧式結構,在每個 Runloop結束時,當前棧頂的Autorelease pool會被銷燬,這樣這個pool裏的每一個Object(就是autorelease的對 象)會被release。那什麼是一個Runloop呢?一個UI事件,Timer call, delegate call, 都會是一個新的 Runloop
1三、iOS有沒有垃圾回收?
Objective-C 2.0也是有垃圾回收機制的,可是隻能在Mac OS X Leopard 10.5 以上的版本使用。
1四、tableView的重用機制?
查看UITableView頭文件,會找到NSMutableArray* visiableCells,和 NSMutableDictnery* reusableTableCells兩個結構。visiableCells內保存當前顯示的 cells,reusableTableCells保存可重用的cells。
TableView顯示之初,reusableTableCells爲空,那麼 tableView dequeueReusableCellWithIdentifier:CellIdentifier返回nil。開始的cell都 是經過 [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 來建立,並且cellForRowAtIndexPath只是調用最大顯示cell數的次數。
好比:有100條數據,iPhone一屏最多顯示10個cell。程序最開始顯示TableView的狀況是:
1.用 [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 建立10次cell,並給cell指定一樣的重用標識(固然,能夠爲不一樣顯示類型的cell指定不一樣的標識)。而且10個cell所有都加入到 visiableCells數組,reusableTableCells爲空。
2.向下拖動tableView,當cell1徹底移出屏幕,而且cell11(它也是alloc出來的,緣由同上)徹底顯示出來的時候。 cell11加入到visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。
3.接着向下拖動tableView,由於reusableTableCells中已經有值,因此,當須要顯示新的 cell,cellForRowAtIndexPath再次被調用的時 候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。 cell1加入到visiableCells,cell1移出reusableTableCells;cell2移出 visiableCells,cell2加入到reusableTableCells。以後再須要顯示的Cell就能夠正常重用了。
1五、ViewController 的loadView、viewDidLoad、viewDidUnload分別是何時調用的,在自定義ViewCointroller時在這幾個函數中應該作什麼工做?
由init、loadView、viewDidLoad、viewDidUnload、dealloc的關係提及
init方法
在init方法中實例化必要的對象(聽從LazyLoad思想)
init方法中初始化ViewController自己
loadView方法
當view須要被展現而它倒是nil時,viewController會調用該方法。不要直接調用該方法。
若是手工維護views,必須重載重寫該方法
若是使用IB維護views,必須不能重載重寫該方法
loadView和IB構建view
你在控制器中實現了loadView方法,那麼你可能會在應用運行的某個時候被內存管理控制調用。 若是設備內存不足的時候, view 控制器會收到 didReceiveMemoryWarning的消息。 默認的實現是檢查當前控制器的view是否在使用。若是它的view不在當前正在使用的 view hierarchy裏面,且你的控制器實現了loadView方法,那麼這個view將被release, loadView方法將被再次調用 來建立一個新的view。
viewDidLoad方法
viewDidLoad 此方法只有當view從nib文件初始化的時候才被調用。
重載重寫該方法以進一步定製view
在iPhone OS 3.0及以後的版本中,還應該重載重寫viewDidUnload來釋放對view的任何索引
viewDidLoad後調用數據Model
viewDidUnload方法
當系統內存吃緊的時候會調用該方法(注:viewController沒有被dealloc)
內存吃緊時,在iPhone OS 3.0以前didReceiveMemoryWarning是釋放無用內存的惟一方式,可是OS 3.0及之後viewDidUnload方法是更好的方式
在該方法中將全部IBOutlet(不管是property仍是實例變量)置爲nil(系統release view時已經將其release掉了)
在該方法中釋放其餘與view有關的對象、其餘在運行時建立(但非系統必須)的對象、在viewDidLoad中被建立的對象、緩存數據 等 release對象後,將對象置爲nil(IBOutlet只須要將其置爲nil,系統release view時已經將其release掉了)
通常認爲viewDidUnload是viewDidLoad的鏡像,由於當view被從新請求時,viewDidLoad還會從新被執行
viewDidUnload中被release的對象必須是很容易被從新建立的對象(好比在viewDidLoad或其餘方法中建立的對象),不要release用戶數據或其餘很難被從新建立的對象
dealloc方法
viewDidUnload和dealloc方法沒有關聯,dealloc仍是繼續作它該作的事情
1六、ViewController的didReceiveMemoryWarning是在何時調用的?默認的操做是什麼?
當程序接到內存警告時View Controller將會收到這個消息:didReceiveMemoryWarning
從iOS3.0開始,不須要重載這個函數,把釋放內存的代碼放到viewDidUnload中去。
這個函數的默認實現是:檢查controller是否能夠安全地釋放它的view(這裏加粗的view指的是controller的view屬性),好比view自己沒有superview而且能夠被很容易地重建(從nib或者loadView函數)。
若是view能夠被釋放,那麼這個函數釋放view並調用viewDidUnload。
你能夠重載這個函數來釋放controller中使用的其餘內存。但要記得調用這個函數的super實現來容許父類(通常是UIVIewController)釋放view。
若是你的ViewController保存着view的子view的引用,那麼,在早期的iOS版本中,你應該在這個函數中來釋放這些引用。而在iOS3.0或更高版本中,你應該在viewDidUnload中釋放這些引用。
1七、列舉Cocoa中常見的集中多線程的實現,並談談多線程安全的幾種解決辦法,通常什麼地方會用到多線程?
NSThread,GCD等。儘可能用上層分裝好的方法去實現多線程而不是手動調用NSThread。
1八、怎麼理解MVC,在Cocoa中MVC是怎麼實現的?
Model: 表明你的應用程序是什麼(不是怎麼展示)
Controller: 控制你的Model怎麼展示給用戶(UI邏輯)
View: Controller的奴隸。。。
1 Model,Controller,View相互通信的規則:
Controller能夠直接和Model通訊
Controller也能夠直接和View通訊
Model和View永遠不能直接通訊
iOS中View和Controller的通訊是透明和固定的,主要經過outlet和action實現
View使用Delegate接口和Controller同步信息
View不直接和數據通訊,使用dataSource接口從Controller處獲取數據
View的delegate和dataSource通常就是Controller
Controller負責爲View翻譯和格式化Model的數據
Model使用Notification & KVO的方式分發數據更新信息,Controller能夠有選擇的監聽本身感興趣的信息。
View也能夠監聽廣播信息,但通常不是Model發出的信息
一個完整的App就是不少MVC的集合
1九、delegate和notification區別,分別在什麼狀況下使用?
Delegate:
消息的發送者(sender)告知接收者(receiver)某個事件將要發生,delegate贊成然而後發送者響應事件,delegate機制使得接收者能夠改變發送者的行爲。一般發送者和接收者的關係是直接的一對多的關係。
Notification:
消息的發送者告知接收者事件已經發生或者將要發送,僅此而已,接收者並不能反過來影響發送者的行爲。一般發送者和接收者的關係是間接的多對多關係。
1. 效率確定是delegate比nsnotification高。
2. delegate方法比notification更加直接,最典型的特徵是,delegate方法每每須要關注返回值,也就是delegate方法 的結果。好比-windowShouldClose:,須要關心返回的是yes仍是no。因此delegate方法每每包含should這個很傳神的詞。 也就是比如你作個人delegate,我會問你我想關閉窗口你願意嗎?你須要給我一個答案,我根據你的答案來決定如何作下一步。相反 的,notification最大的特點就是不關心接受者的態度,我只管把通告放出來,你接受不接受就是你的事情,同時我也不關心結果。因此 notification每每用did這個詞彙,好比NSWindowDidResizeNotification,那麼nswindow對象放出這個 notification後就什麼都無論了也不會等待接受者的反應。
1)兩個模塊之間聯繫不是很緊密,就用notification傳值,例如多線程之間傳值用notificaiton。
2)delegate只是一種較爲簡單的回調,且主要用在一個模塊中,例如底層功能完成了,須要把一些值傳到上層去,就事先把上層的函數經過 delegate傳到底層,而後在底層call這個delegate,它們都在一個模塊中,完成一個功能,例如 說 NavgationController 從 B 界面到A 點返回按鈕 (調用popViewController方法) 能夠用delegate 比較好。
20、self.跟self什麼區別?
2一、id、nil表明什麼?
id和void *並不是徹底同樣。在上面的代碼中,id是指向struct objc_object的一個指針,這個意思基本上是說,id是一個指向任何 一個繼承了Object(或者NSObject)類的對象。須要注意的是id是一個指針,因此你在使用id的時候不須要加星號。好比id foo=nil 定義了一個nil指針,這個指針指向NSObject的一個任意子類。而id *foo=nil則定義了一個指針,這個指針指向另外一個指針,被指向的這個 指針指向NSObject的一個子類。
nil和C語言的NULL相同,在objc/objc.h中定義。nil表示一個Objctive-C對象,這個對象的指針指向空(沒有東西就是空)。
首字母大寫的Nil和nil有一點不同,Nil定義一個指向空的類(是Class,而不是對象)。
SEL是「selector」的一個類型,表示一個方法的名字
Method(咱們常說的方法)表示一種類型,這種類型與selector和實現(implementation)相關
IMP定義爲 id (*IMP) (id, SEL, …)。這樣說來, IMP是一個指向函數的指針,這個被指向的函數包括id(「self」指針),調用的SEL(方法名),再加上一些其餘參數.說白了IMP就是實現方法。
2二、內存管理 Autorelease、retain、copy、assign的set方法和含義?
1,你初始化(alloc/init)的對象,你須要釋放(release)它。例如:
NSMutableArray aArray = [[NSArray alloc] init]; 後,須要 [aArray release];
2,你retain或copy的,你須要釋放它。例如:
[aArray retain] 後,須要 [aArray release];
3,被傳遞(assign)的對象,你須要斟酌的retain和release。例如:
obj2 = [[obj1 someMethod] autorelease];
對象2接收對象1的一個自動釋放的值,或傳遞一個基本數據類型(NSInteger,NSString)時:你或但願將對象2進行retain,以防止它在被使用以前就被自動釋放掉。可是在retain後,必定要在適當的時候進行釋放。
關於索引計數(Reference Counting)的問題
retain值 = 索引計數(Reference Counting)
NSArray對象會retain(retain值加一)任何數組中的對象。當NSArray被卸載(dealloc)的時候,全部數組中的對象會被 執行一次釋放(retain值減一)。不只僅是NSArray,任何收集類(Collection Classes)都執行相似操做。例如 NSDictionary,甚至UINavigationController。
Alloc/init創建的對象,索引計數爲1。無需將其再次retain。
[NSArray array]和[NSDate date]等「方法」創建一個索引計數爲1的對象,可是也是一個自動釋放對象。因此是本地臨時對象,那麼無所謂了。若是是打算在全Class中使用的變量(iVar),則必須retain它。
缺省的類方法返回值都被執行了「自動釋放」方法。(*如上中的NSArray)
在類中的卸載方法「dealloc」中,release全部未被平衡的NS對象。(*全部未被autorelease,而retain值爲1的)
2三、類別的做用?
有時咱們須要在一個已經定義好的類中增長一些方法,而不想去重寫該類。好比,當工程已經很大,代碼量比較多,或者類中已經包住不少方法,已經有其餘代碼調用了該類建立對象並使用該類的方法時,能夠使用類別對該類擴充新的方法。
注意:類別只能擴充方法,而不能擴充成員變量。
2四、委託(舉例)
委託代理(degegate),顧名思義,把某個對象要作的事情委託給別的對象去作。那麼別的對象就是這個對象的代理,代替它來打理要作的事。反映到程序中,首先要明確一個對象的委託方是哪一個對象,委託所作的內容是什麼。
委託機制是一種設計模式,在不少語言中都用到的,這只是個通用的思想,網上會有不少關於這方面的介紹。
那麼在蘋果開發過程當中,用到委託的程序實現思想以下,我主要拿如何在視圖之間傳輸信息作個例子。
譬如:在兩個頁面(UIIview視圖對象)實現傳值,用委託(delegate)能夠很好作到!
方法:
類A
@interface A:UIView
id transparendValueDelegate;
@property(nomatic, retain) id transparendValueDelegate;
@end
@implemtion A
@synthesize transparendValueDelegate
-(void)Function
{
NSString* value = @"hello";
//讓代理對象執行transparendValue動做
[transparendValueDelegate transparendValue: value];
}
@end
類B
@interface B:UIView
NSString* value;
@end
@implemtion B
-(void)transparendValue:(NSString*)fromValue
{
value = fromValue;
NSLog(@"the value is %@ ",value);
}
@end
//下面的設置A代理委託對象爲B
//在定義A和B類對象處:
A* a = [[A alloc] init];
B* b = [[B alloc] init];
a. transparendValueDelegate = b;//設置對象a代理爲對象b
這樣在視圖A和B之間能夠經過委託來傳值!
2五、retainCount?
26..屬性readwrite,readonly,assign,retain,copy,nonatomic 各是什麼做用,在那種狀況下用
assign:指定setter方法用簡單的賦值,這是默認操做。你能夠對標量類型(如int)使用這個屬性。你能夠想象一個float,它不是一個對象,因此它不能retain、copy。
retain:指定retain應該在後面的對象上調用,前一個值發送一條release消息。你能夠想象一個NSString實例,它是一個對象,並且你可能想要retain它。
copy:指定應該使用對象的副本(深度複製),前一個值發送一條release消息。基本上像retain,可是沒有增長引用計數,是分配一塊新的內存來放置它。
readonly:將只生成getter方法而不生成setter方法(getter方法沒有get前綴)。
readwrite:默認屬性,將生成不帶額外參數的getter和setter方法(setter方法只有一個參數)。
atomic:對於對象的默認屬性,就是setter/getter生成的方法是一個原子操做。若是有多個線程同時調用setter的話,不會出現某一個線程執行setter所有語句以前,另外一個線程開始執行setter的狀況,相關於方法頭尾加了鎖同樣。
nonatomic:不保證setter/getter的原子性,多線程狀況下數據可能會有問題。
27.類變量的@protected ,@private ,@public ,@package聲明各有什麼含義
Objective-C 對存取權限的設定。也是變量的做用域。
protected 該類和全部的子類中的方法能夠直接訪問這樣的變量,這是默認的。
private — 該類中的方法能夠訪問這樣的變量,子類不能夠。 public — 除了本身和子類中的方法外,也能夠被其餘類或者其餘模塊中的方法所訪問。開放性最大。 package — 對於64位圖像,這樣的成員變量能夠在實現這個類的圖像中隨意訪問。
28.淺拷貝和深拷貝區別是什麼
簡單的來講就是,在有指針的狀況下,淺拷貝只是增長了一個指針指向已經存在的內存,而深拷貝就是增長一個指針而且申請一個新的內存,使這個增長的指針指向這個新的內存,採用深拷貝的狀況下,釋放內存的時候就不會出如今淺拷貝時重複釋放同一內存的錯誤
29.Cocoa中與虛基類的概念麼?怎麼簡潔的實現
30.NSString 和 NSMutableString 有什麼區別
NSString至關於一個const char* 不能夠改變。
而 NSMutableString至關於 char* 能夠改變內部的內容。
31.自動釋放池跟GC有什麼區別?iPhone上有GC麼?[pool release] 和[pool drain]有什麼區別
」Autorelease Pools」(自動釋放池)在應用中的使用技巧。
1,Autorelease Pools概要
一個」Autorelease Pool」實例中「包含」其它各類調用了」autorelease」方法的對象。當它釋放時,其中全部被管理對象都會收 到」relrease」的消信。注意,同一個對象能夠被屢次調用」autorelease」方法,並能夠放到同一個」Autorelease Pool」 中。引入這個自動釋放池機制,對象的」autorelease」方法代替」relrease」方法能夠延長它的生命週期,直接到當 前」Autorelrease Pool」釋放。若是想讓此對象的生命週期超過」Autorelease Pool」,還能夠再次」retain」,呵 呵,有意思吧?且讓我慢慢道來。
Cocoa老是認爲當前至少有一個」Autorelease Pool」對象是可用的。若此對象並不存在,你調用的」autorelease」的全部對象都不會被自動釋放掉,可想而知,形成內存泄露。Cocoa把這個錯誤信息寫入日誌??僅僅是爲了之後分析。
你能夠用」alloc」與」init」方法建立一個」NSAutoreleasePool」對象,而且能夠調用」release」或」drain」 (」release」與」drain」的區別是」drain」在有GC的環境中會引發GC回收操做,」release」反之。但在非GC環境中,二者相 同。官方的說法是爲了程序的兼容性,應該考慮用」drain」代替」release」,)方法來回收它(調用它的」autorelease」 或」retain」方法會引發異常)。在一個完整的上下文最後」Autorelease Pool」對象應該被」release」掉(在方法內或一段循環 體內建立的」Autorelease Pool」對象)。
「Autorelease Pools」的全部實例在棧中管理(咱們暫時叫他「自動釋放池棧」),而且它們是能夠被嵌套的(父生子,子生孫。。。子子孫 孫 ^_^)。例如,當咱們建立一個」Autorelease Pool」對象後,它就被自動放到「自動釋放池棧」的棧頂。當本池對象回收時,它就隨之從 這個棧中POP掉。那麼也就是說,當任何一個對象調用」autorelease」方法後,它會被放入當前線程中當前棧頂的自動釋放池中。
接下來咱們聊聊」Autorelease Pools」的嵌套問題。在你的應用中,你能夠任意多的建立」Autorelease Pool」對象,而這些 對象被當前線程的「自動釋放池棧」所管理。那麼除了一個接一個的順序建立並銷燬它的狀況外,還有一種使用方式,就是嵌套式的建立與使用。例如:在你的主函 數建立了一個」autorelease pool」,而後又調用了建立了」autorelease pool」實例的其它方法;或是在外循環中建立 了」Autorelease Pool」的實例,而內循環中也作了相同的事情。有意思吧,呵呵,嵌套的機制使父Pool實例釋放後,它的全部子Pool也 將釋放。但這裏還存在一些反作用,後續文章會詳細討論。
「Application kit」在一個事件循環裏會自動建立一個」autorelease pool」。像鼠標鍵的按下與釋放,因此你編寫的代碼一般不須要考慮太多這方面的事情。固然,有如下三種狀況你會建立與銷燬本身的Pool實例:
1,應用不是基於」Application Kit」,像」Command-line tool」,由於它並無內置的」autorelease pools」的支持。
2,建立線程,你必需在線程開始時建立一個」Autorelease Pool」實例。反之,會形成內存池露(會在之後的文章詳細說明線程與池的技巧)。
3,一個循環內建立了太多的臨時對象,你應該爲他們建立一個」Autorelease Pool」對象,並在下次循還前銷燬它們。
2,自動釋放池中的」Non-AppKit」應用
在」Non-AppKit」應用中使用自動釋放池的機制實際上是至關簡單的事情。你僅僅須要在main()起始處建立」Autorelease Pool」 對象,並在結尾處釋放掉它。就像在Xcode的Foundation Tool的建立模版裏寫的同樣。這個確保你在應用生命週期內至少有一 個」Autorelease Pool」是可用的。可是,這也使全部在此期間的全部」autorelease」的對象都必需在應用結束後才被釋放。這也許 會引發在應用的使用中不斷的增加,因此,你仍然考慮在不一樣的做用域建立新的」Autorelease Pool」。
大多應用中都存在各類級別的循環機制。在這些應用中,你能夠在每一個循環內的開頭建立一個」Autorelease Pool」對象,並在結尾處釋放掉它。
例如:
void main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *args = [[NSProcessInfo processInfo] arguments];
unsigned count, limit = [args count];
for (count = 0; count < limit; count++)
{
NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
NSString *fileContents;
NSString *fileName;
fileName = [args objectAtIndex:count];
fileContents = [[[NSString alloc] initWithContentsOfFile:fileName] autorelease];
// this is equivalent to using stringWithContentsOfFile:
[loopPool release];
}
[pool drain];
exit (EXIT_SUCCESS);
}
在命令行中處理全部以參數傳來的文件。一次循環處理一個文件。在循環的開頭建立一個」NSAutoreleasePool」對象,並在循環結束時釋放掉。 所以,任何在其中建立並調用「autorelease」的對象都將添加到這個Pool實例中,當本池被釋放後,這些對象也將被回收。注意,任何在做用域內 建立的」autoreleased」對象(像」fileName」),雖然並無顯示的調用」autorelease」方法,但都將被當前池所管理並釋 放。
32.C和obj-c 如何混用
1)obj-c的編譯器處理後綴爲m的文件時,能夠識別obj-c和c的代碼,處理mm文件能夠識別obj-c,c,c++代碼,但cpp文件必須只能用c/c++代碼,並且cpp文件include的頭文件中,也不能出現obj-c的代碼,由於cpp只是cpp
2)在mm文件中混用cpp直接使用便可,因此obj-c混cpp不是問題
3)在cpp中混用obj-c其實就是使用obj-c編寫的模塊是咱們想要的。
若是模塊以類實現,那麼要按照cpp class的標準寫類的定義,頭文件中不能出現obj-c的東西,包括#import cocoa的。實現文件中,即類的實現代碼中能夠使用obj-c的東西,能夠import,只是後綴是mm。
若是模塊以函數實現,那麼頭文件要按c的格式聲明函數,實現文件中,c++函數內部能夠用obj-c,但後綴仍是mm或m。
總結:只要cpp文件和cpp include的文件中不包含obj-c的東西就能夠用了,cpp混用obj-c的關鍵是使用接口,而不能直接使用實現代 碼,實際上cpp混用的是obj-c編譯後的o文件,這個東西實際上是無差異的,因此能夠用。obj-c的編譯器支持cpp
33.響應者鏈是什麼
響應者鏈是Application Kit事件處理架構的中心機制。它由一系列連接在一塊兒的響應者對象組成,事件或者動做消息能夠沿着這些對象進行傳 遞。如圖6-20顯示的那樣,若是一個響應者對象不能處理某個事件或動做-也就是說,它不響應那個消息,或者不認識那個事件,則將該消息從新發送給鏈中的 下一個響應者。消息沿着響應者鏈向上、向更高級別的對象傳遞,直到最終被處理(若是最終仍是沒有被處理,就會被拋棄)。
當Application Kit在應用程序中構造對象時,會爲每一個窗口創建響應者鏈。響應者鏈中的基本對象是NSWindow對象及其視圖層次。在視圖層次中級別較低的視圖將比級別更高的視圖優先得到處理事件或動做消息的機會。NSWindow中保有一個第一響應者的引用,它一般是當前窗口中處於選擇狀態的視圖,窗口一般把響應消息的機會首先給它。對於事件消息,響應者鏈一般以發生事件的窗口對應的NSWindow對象做爲結束,雖然其它對象也能夠做爲下一個響應者被加入到NSWindow對象的後面。
34..UIscrollVew用到了什麼設計模式?還能再foundation庫中找到相似的嗎?
組合模式composition,全部的container view都用了這個模式
觀察者模式observer,全部的UIResponder都用了這個模式。
模板(Template)模式,全部datasource和delegate接口都是模板模式的典型應用
33. .timer的間隔週期準嗎?爲何?怎樣實現一個精準的timer?
NSTimer能夠精確到50-100毫秒.
NSTimer不是絕對準確的,並且中間耗時或阻塞錯過下一個點,那麼下一個點就pass過去了
此份面試題包含40個題目,是如今網上能搜索到的一個比較熱的一份,可是答案並非很詳細和完整,基本答案來着cocoaChina,和一些本身的補充。
34.Difference between shallow copy and deep copy?
淺複製和深複製的區別?
答案:淺層複製:只複製指向對象的指針,而不復制引用對象自己。
深層複製:複製引用對象自己。
意思就是說我有個A對象,複製一份後獲得A_copy對象後,對於淺複製來講,A和A_copy指向的是同一個內存資源,複製的只不過是是一個指針,對象自己資源
仍是隻有一份,那若是咱們對A_copy執行了修改操做,那麼發現A引用的對象一樣被修改,這其實違背了咱們複製拷貝的一個思想。深複製就好理解了,內存中存在了
兩份獨立對象自己。
用網上一哥們通俗的話將就是:
淺複製比如你和你的影子,你完蛋,你的影子也完蛋
深複製比如你和你的克隆人,你完蛋,你的克隆人還活着。
35.What is advantage of categories? What is difference between implementing a category and inheritance?
類別的做用?繼承和類別在實現中有何區別?
答案:category 能夠在不獲悉,不改變原來代碼的狀況下往裏面添加新的方法,只能添加,不能刪除修改。
而且若是類別和原來類中的方法產生名稱衝突,則類別將覆蓋原來的方法,由於類別具備更高的優先級。
類別主要有3個做用:
(1)將類的實現分散到多個不一樣文件或多個不一樣框架中。
(2)建立對私有方法的前向引用。
(3)向對象添加非正式協議。
繼承能夠增長,修改或者刪除方法,而且能夠增長屬性。
36.Difference between categories and extensions?
類別和類擴展的區別。
答案:category和extensions的不一樣在於後者能夠添加屬性。另外後者添加的方法是必需要實現的。
extensions能夠認爲是一個私有的Category。
37.Difference between protocol in objective c and interfaces in java?
oc中的協議和java中的接口概念有何不一樣?
答案:OC中的代理有2層含義,官方定義爲 formal和informal protocol。前者和Java接口同樣。
informal protocol中的方法屬於設計模式考慮範疇,不是必須實現的,可是若是有實現,就會改變類的屬性。
其實關於正式協議,類別和非正式協議我很早前學習的時候大體看過,也寫在了學習教程裏
「非正式協議概念其實就是類別的另外一種表達方式「這裏有一些你可能但願實現的方法,你能夠使用他們更好的完成工做」。
這個意思是,這些是可選的。好比我門要一個更好的方法,咱們就會申明一個這樣的類別去實現。而後你在後期能夠直接使用這些更好的方法。
這麼看,總以爲類別這玩意兒有點像協議的可選協議。"
如今來看,其實protocal已經開始對二者都統一和規範起來操做,由於資料中說「非正式協議使用interface修飾「,
如今咱們看到協議中兩個修飾詞:「必須實現(@requied)」和「可選實現(@optional)」。
38.What are KVO and KVC?
答案:kvc:鍵 - 值編碼是一種間接訪問對象的屬性使用字符串來標識屬性,而不是經過調用存取方法,直接或經過實例變量訪問的機制。
不少狀況下能夠簡化程序代碼。apple文檔其實給了一個很好的例子。
kvo:鍵值觀察機制,他提供了觀察某一屬性變化的方法,極大的簡化了代碼。
具體用看到嗯哼用到過的一個地方是對於按鈕點擊變化狀態的的監控。
好比我自定義的一個button
[cpp]
[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil];
#pragma mark KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
([keyPath isEqualToString:@"highlighted"] ) {
[self setNeedsDisplay];
}
}
對於系統是根據keypath去取的到相應的值發生改變,理論上來講是和kvc機制的道理是同樣的。
對於kvc機制如何經過key尋找到value:
「當經過KVC調用對象時,好比:[self valueForKey:@」someKey」]時,程序會自動試圖經過幾種不一樣的方式解析這個調用。首先 查找對象是否帶有 someKey 這個方法,若是沒找到,會繼續查找對象是否帶有someKey這個實例變量(iVar),若是尚未找到,程序會繼續 試圖調用 -(id) valueForUndefinedKey:這個方法。若是這個方法仍是沒有被實現的話,程序會拋出一個 NSUndefinedKeyException異常錯誤。
(cocoachina.com注:Key-Value Coding查找方法的時候,不只僅會查找someKey這個方法,還會查找 getsomeKey這個方法,前面加一個get,或者_someKey以及_getsomeKey這幾種形式。同時,查找實例變量的時候也會不只僅查找 someKey這個變量,也會查找_someKey這個變量是否存在。)
設計valueForUndefinedKey:方法的主要目的是當你使用-(id)valueForKey方法從對象中請求值時,對象可以在錯誤發生前,有最後的機會響應這個請求。這樣作有不少好處,下面的兩個例子說明了這樣作的好處。「
來至cocoa,這個說法應該挺有道理。
由於咱們知道button倒是存在一個highlighted實例變量.所以爲什麼上面咱們只是add一個相關的keypath就好了,
能夠按照kvc查找的邏輯理解,就說的過去了。
39.What is purpose of delegates?
代理的做用?
答案:代理的目的是改變或傳遞控制鏈。容許一個類在某些特定時刻通知到其餘類,而不須要獲取到那些類的指針。能夠減小框架複雜度。
另一點,代理能夠理解爲java中的回調監聽機制的一種相似。
40.What are mutable and immutable types in Objective C?
oc中可修改和不能夠修改類型。
答案:可修改不可修改的集合類。這個我我的簡單理解就是可動態添加修改和不可動態添加修改同樣。
好比NSArray和NSMutableArray。前者在初始化後的內存控件就是固定不可變的,後者能夠添加等,能夠動態申請新的內存空間。
41.When we call objective c is runtime language what does it mean?
咱們說的oc是動態運行時語言是什麼意思?
答案:多態。 主要是將數據類型的肯定由編譯時,推遲到了運行時。
這個問題其實淺涉及到兩個概念,運行時和多態。
簡單來講,運行時機制使咱們直到運行時纔去決定一個對象的類別,以及調用該類別對象指定方法。
多態:不一樣對象以本身的方式響應相同的消息的能力叫作多態。意思就是假設生物類(life)都用有一個相同的方法-eat;
那人類屬於生物,豬也屬於生物,都繼承了life後,實現各自的eat,可是調用是咱們只需調用各自的eat方法。
也就是不一樣的對象以本身的方式響應了相同的消息(響應了eat這個選擇器)。
所以也能夠說,運行時機制是多態的基礎?~~~
42.what is difference between NSNotification and protocol?
通知和協議的不一樣之處?
答案:協議有控制鏈(has-a)的關係,通知沒有。
首先我一開始也不太明白,什麼叫控制鏈(專業術語了~)。可是簡單分析下通知和代理的行爲模式,咱們大體能夠有本身的理解
簡單來講,通知的話,它能夠一對多,一條消息能夠發送給多個消息接受者。
代理按咱們的理解,到不是直接說不能一對多,好比咱們知道的明星經濟代理人,不少時候一個經濟人負責好幾個明星的事務。
只是對於不一樣明星間,代理的事物對象都是不同的,一一對應,不可能說明天要處理A明星要一個發佈會,代理人發出處理髮佈會的消息後,別稱B的
發佈會了。可是通知就不同,他只關心發出通知,而不關心多少接收到感興趣要處理。
所以控制鏈(has-a從英語單詞大體能夠看出,單一擁有和可控制的對應關係。
43.What is push notification?
什麼是推送消息?
答案:太簡單,不做答~~~~~~~~~~
這是cocoa上的答案。
其實到不是說太簡單,只是太泛泛的一個概念的東西。就比如說,什麼是人。
推送通知更是一種技術。
簡單點就是客戶端獲取資源的一種手段。
普通狀況下,都是客戶端主動的pull。
推送則是服務器端主動push。
44.Polymorphism?
關於多態性
答案:多態,子類指針能夠賦值給父類。
這個題目其實能夠出到一切面向對象語言中,
所以關於多態,繼承和封裝基本最好都有個自我意識的理解,也並不是必定要把書上資料上寫的能背出來。
最重要的是轉化成自我理解。
45.Singleton?
對於單例的理解
答案:11,12題目其實出的有點泛泛的感受了,可能說是編程語言須要或是必備的基礎。
基本能用熟悉的語言寫出一個單例,以及能夠運用到的場景或是你編程中碰到過運用的此種模式的框架類等。
進一步點,考慮下如何在多線程訪問單例時的安全性。
46.What is responder chain?
說說響應鏈
答案: 事件響應鏈。包括點擊事件,畫面刷新事件等。在視圖棧內從上至下,或者從下之上傳播。
能夠說點事件的分發,傳遞以及處理。具體能夠去看下touch事件這塊。由於問的太抽象化了
嚴重懷疑題目出到越後面就越籠統。
47.Difference between frame and bounds?
frame和bounds有什麼不一樣?
答案:frame指的是:該view在父view座標系統中的位置和大小。(參照點是父親的座標系統)
bounds指的是:該view在自己座標系統中 的位置和大小。(參照點是自己座標系統)
48.Difference between method and selector?
方法和選擇器有何不一樣?
答案:selector是一個方法的名字,method是一個組合體,包含了名字和實現.
詳情能夠看apple文檔。
49.Is there any garbage collection mechanism in Objective C.?
OC的垃圾回收機制?
答案: OC2.0有Garbage collection,可是iOS平臺不提供。
通常咱們瞭解的objective-c對於內存管理都是手動操做的,可是也有自動釋放池。
可是差了大部分資料,貌似不要和arc機制搞混就行了。
求更多~~
50.NSOperation queue?
答案:存放NSOperation的集合類。
操做和操做隊列,基本能夠當作java中的線程和線程池的概念。用於處理ios多線程開發的問題。
網上部分資料提到一點是,雖然是queue,可是卻並非帶有隊列的概念,放入的操做並不是是按照嚴格的先進現出。
這邊又有個疑點是,對於隊列來講,先進先出的概念是Afunc添加進隊列,Bfunc緊跟着也進入隊列,Afunc先執行這個是必然的,
可是Bfunc是等Afunc徹底操做完之後,B纔開始啓動而且執行,所以隊列的概念離亂上有點違背了多線程處理這個概念。
可是轉念一想其實能夠參考銀行的取票和叫號系統。
所以對於A比B先排隊取票可是B率先執行完操做,咱們亦然能夠感性認爲這仍是一個隊列。
可是後來看到一票關於這操做隊列話題的文章,其中有一句提到
「由於兩個操做提交的時間間隔很近,線程池中的線程,誰先啓動是不定的。」
瞬間以爲這個queue名字有點忽悠人了,還不如pool~
綜合一點,咱們知道他能夠比較大的用處在於能夠幫組多線程編程就行了。
51.What is lazy loading?
答案:懶漢模式,只在用到的時候纔去初始化。
也能夠理解成延時加載。
我以爲最好也最簡單的一個列子就是tableView中圖片的加載顯示了。
一個延時載,避免內存太高,一個異步加載,避免線程堵塞。
52.Can we use two tableview controllers on one viewcontroller?
是否在一個視圖控制器中嵌入兩個tableview控制器?
答案:一個視圖控制只提供了一個View視圖,理論上一個tableViewController也不能放吧,
只能說能夠嵌入一個tableview視圖。固然,題目自己也有歧義,若是不是咱們定性思惟認爲的UIViewController,
而是宏觀的表示視圖控制者,那咱們卻是能夠把其當作一個視圖控制者,它能夠控制多個視圖控制器,好比TabbarController
那樣的感受。
53.Can we use one tableview with two different datasources? How you will achieve this?
一個tableView是否能夠關聯兩個不一樣的數據源?你會怎麼處理?
答案:首先咱們從代碼來看,數據源如何關聯上的,實際上是在數據源關聯的代理方法裏實現的。
所以咱們並不關心如何去關聯他,他怎麼關聯上,方法只是讓我返回根據本身的須要去設置如相關的數據源。
所以,我以爲能夠設置多個數據源啊,可是有個問題是,你這是想幹嗎呢?想讓列表如何顯示,不一樣的數據源分區塊顯示?