IOS面試題

引用自:http://blog.sina.com.cn/s/blog_a7c44c880101aibh.htmlhtml



一、Object-C有多繼承嗎?沒有的話用什麼代替?cocoa 中全部的類都是NSObject 的子類
多繼承在這裏是用protocol 委託代理 來實現的
你不用去考慮繁瑣的多繼承 ,虛基類的概念.
ood
的多態特性  obj-c 中經過委託來實現.

二、Object-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, 都會是一個新的Runloop1三、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後調用數據ModelviewDidUnload方法當系統內存吃緊的時候會調用該方法(注: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的奴隸。。。

Model,Controller,View相互通信的規則:
ios

  1. Controller能夠直接和Model通訊c++

  2. Controller也能夠直接和View通訊程序員

  3. Model和View永遠不能直接通訊面試

  4. iOS中View和Controller的通訊是透明和固定的,主要經過outlet和action實現objective-c

  5. View使用Delegate接口和Controller同步信息設計模式

  6. View不直接和數據通訊,使用dataSource接口從Controller處獲取數據數組

  7. View的delegate和dataSource通常就是Controller緩存

  8. Controller負責爲View翻譯和格式化Model的數據安全

  9. Model使用Notification & KVO的方式分發數據更新信息,Controller能夠有選擇的監聽本身感興趣的信息。

  10. View也能夠監聽廣播信息,但通常不是Model發出的信息

  11. 一個完整的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) (idSEL, …)。這樣說來, 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在應用程序中構造對象時,會爲每一個窗口創建響應者鏈。響應者鏈中的基本對象是對象及其視圖層次。在視圖層次中級別較低的視圖將比級別更高的視圖優先得到處理事件或動做消息的機會。中保有一個第一響應者的引用,它一般是當前窗口中處於選擇狀態的視圖,窗口一般把響應消息的機會首先給它。對於事件消息,響應者鏈一般以發生事件的窗口對應的對象做爲結束,雖然其它對象也能夠做爲下一個響應者被加入到對象的後面。



34..UIscrollVew用到了什麼設計模式?還能再foundation庫中找到相似的嗎?
組合模式composition,全部的container view都用了這個模式
觀察者模式observer,全部的UIResponder都用了這個模式。
NSWindowNSWindowNSWindowNSWindow
模板(Template)模式,全部datasource和delegate接口都是模板模式的典型應用







33. .timer的間隔週期準嗎?爲何?怎樣實現一個精準的timer?



NSTimer能夠精確到50-100毫秒.


NSTimer不是絕對準確的,並且中間耗時或阻塞錯過下一個點,那麼下一個點就pass過去了






34.
相關文章
相關標籤/搜索