[轉]那些著名或非著名的iOS面試題(下)

來源:互聯網
上載者:User

標籤:

1. Runtime

Objective-C 是面相運行時的語言(runtime oriented language),就是說它會儘可能的把編譯和連結時要執行的邏輯延遲到運行時。這就給了你很大的靈活性,你可以按需要把訊息重新導向給合適的對象,你甚 至可以交換方法的實現,等等。

RunTime簡稱運行時。就是系統在啟動並執行時候的一些機制,其中最主要的是訊息機制。OC的函數調用成為訊息發送。屬於動態調用過程。在編譯的時候並不能決定真正調用哪個函數(事實證明,在編 譯階段,OC可以調用任何函數,即使這個函數並未實現,只要申明過就不會報錯。而C語言在編譯階段就會報錯)。只有在真正啟動並執行時候才會根據函數的名稱找 到對應的函數來調用。

以下面的代碼為例:

1 [obj makeText];

其中obj是一個對象,makeText是一個函數名稱。對於這樣一個簡單的調用。在編譯時間RunTime會將上述代碼轉化成

1 objc_msgSend(obj,@selector(makeText));

首先,編譯器將代碼[obj makeText];轉化為objc_msgSend(obj, @selector (makeText));,在objc_msgSend函數中。首先通過obj的isa指標找到obj對應的class。在Class中先去cache中 通過SEL尋找對應函數method(猜測cache中method列表是以SEL為key通過hash表來儲存的,這樣能提高函數尋找速度),若 cache中未找到。再去methodList中尋找,若methodlist中未找到,則取superClass中尋找。若能找到,則將method加 入到cache中,以方便下次尋找,並通過method中的函數指標跳轉到對應的函數中去執行。

Objective-C Runtime 是什嗎?

Objective-C 的 Runtime 是一個執行階段程式庫(Runtime Library),它是一個主要使用 C 和彙編寫的庫,為 C 添加了面相對象的能力並創造了 Objective-C。這就是說它在類資訊(Class information) 中被載入,完成所有的方法分發,方法轉寄,等等。Objective-C runtime 建立了所有需要的結構體,讓 Objective-C 的面相對象編程變為可能。

Method Swizzling 原理

在Objective-C中調用一個方法,其實是向一個對象發送訊息,尋找訊息的唯一依據是selector的名字。利用Objective-C的動態特性,可以實現在運行時偷換selector對應的方法實現,達到給方法掛鈎的目的。每個類都有一個方法列表,存放著selector的名字和方法實現的映射關係。IMP有點類似函數指標,指向具體的Method實現。

我們可以利用 method_exchangeImplementations 來交換2個方法中的IMP,

我們可以利用 class_replaceMethod 來修改類,

我們可以利用 method_setImplementation 來直接設定某個方法的IMP,……

歸根結底,都是偷換了selector的IMP。

2. GCD實現1,2並行和3串列和45串列,4,5是並行。即3依賴1,2的執行,45依賴3的執行。

關係

隊列組的方式

123456789101112131415161718192021222324252627 - (void) methodone{dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    NSLog(@"%d",1);}); dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    NSLog(@"%d",2);}); dispatch_group_notify(group, dispatch_get_main_queue(), ^{    NSLog(@"3");     dispatch_group_t group1 = dispatch_group_create();     dispatch_group_async(group1, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        NSLog(@"%d",4);    });     dispatch_group_async(group1, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        NSLog(@"%d",5);    }); }); }

串列隊列:隊列中的任務只會順序執行

1 dispatch_queue_t q = dispatch_queue_create(“....”, dispatch_queue_serial);

並行隊列: 隊列中的任務通常會並發執行。

1 dispatch_queue_t q = dispatch_queue_create("......", dispatch_queue_concurrent);

全域隊列:是系統開發的,直接拿過來用就可以;與並行隊列類似,但調試時,無法確認操作所在隊列 。

1 dispatch_queue_t q = dispatch_get_global_queue(dispatch_queue_priority_default, 0);

主隊列:每一個應用開發程式對應唯一一個主隊列,直接get即可;在多線程開發中,使用主隊列更新UI。

1 dispatch_queue_t q = dispatch_get_main_queue();

主隊列是GCD內建的串列隊列,會在主線程中執行。非同步全域並發隊列 開啟新線程,並發執行。

並行隊列裡開啟同步任務是有執行順序的,只有非同步才沒有順序。

串列隊列開啟非同步任務,是有順序的。

串列隊列開啟非同步任務後嵌套同步任務造成死結。

3. 深淺複製和屬性為copy,strong值的變化問題

淺複製:只複製指向對象的指標,而不複製引用對象本身。對於淺複製來說,A和A_copy指向的是同一個記憶體資源,複製的只不個是一個指標,對象本身資源還是只有一份,那如果我們對A_copy執行了修改操作,那麼發現A引用的對象同樣被修改了。深複製就好理解了,記憶體中存在了兩份獨立對象本身。

在Objective-C中並不是所有的對象都支援Copy,MutableCopy,遵守NSCopying協議的類才可以發送Copy訊息,遵守NSMutableCopying協議的類才可以發送MutableCopy訊息。

1234 [immutableObject copy] // 淺拷貝[immutableObject mutableCopy] //深拷貝[mutableObject copy] //深拷貝[mutableObject mutableCopy] //深拷貝

屬性設為copy,指定此屬性的值不可更改,防止可變字串更改自身的值的時候不會影響到對象屬性(如NSString,NSArray,NSDictionary)的值。strong此屬性的指會隨著變化而變化。copy是內容拷貝,strong是指標拷貝。

4.NSTimer建立後,會在哪個線程運行。

用scheduledTimerWithTimeInterval建立的,在哪個線程建立就會被加入哪個線程的RunLoop中就運行在哪個線程。

自己建立的Timer,加入到哪個線程的RunLoop中就運行在哪個線程。

5. KVO,NSNotification,delegate及block區別

KVO就是cocoa架構實現的觀察者模式,一般同KVC搭配使用,通過KVO可以監測一個值的變化,比如View的高度變化。是一對多的關係,一個值的變化會通知所有的觀察者。

NSNotification是通知,也是一對多的使用情境。在某些情況下,KVO和NSNotification是一樣的,都是狀態變化之後告知對方。NSNotification的特點,就是需要被觀察者先主動發出通知,然後觀察者註冊監聽後再來進行響應,比KVO多了發送通知的一步,但是其優點是監聽不局限於屬性的變化,還可以對多種多樣的狀態變化進行監聽,監聽範圍廣,使用也更靈活。

delegate 是代理,就是我不想做的事情交給別人做。比如狗需要吃飯,就通過delegate通知主人,主人就會給他做飯、盛飯、倒水,這些操作,這些狗都不需要關心,只需要調用delegate(代理人)就可以了,由其他類完成所需要的操作。所以delegate是一對一關聯性。

block是delegate的另一種形式,是函數式編程的一種形式。使用情境跟delegate一樣,相比delegate更靈活,而且代理的實現更直觀。

KVO一般的使用情境是資料,需求是資料變化,比如股票價格變化,我們一般使用KVO(觀察者模式)。delegate一般的使用情境是行為,需求是需要別人幫我做一件事情,比如買賣股票,我們一般使用delegate。Notification一般是進行全域通知,比如利好訊息一出,通知大家去買入。delegate是強關聯,就是委託和代理雙方互相知道,你委託別人買股票你就需要知道經紀人,經紀人也不要知道自己的顧客。Notification是弱關聯,利好訊息發出,你不需要知道是誰發的也可以做出相應的反應,同理髮訊息的人也不需要知道接收的人也可以正常發出訊息。

6. 如何讓計時器調用一個類方法

計時器只能調用執行個體方法,但是可以在這個執行個體方法裡面調用靜態方法。

使用計時器需要注意,計時器一定要加入RunLoop中,並且選好model才能運行。scheduledTimerWithTimeInterval方法建立一個計時器並加入到RunLoop中所以可以直接使用。

如果計時器的repeats選擇YES說明這個計時器會重複執行,一定要在合適的時機調用計時器的invalid。不能在dealloc中調用,因為一旦設定為repeats 為yes,計時器會強持有self,導致dealloc永遠不會被調用,這個類就永遠無法被釋放。比如可以在viewDidDisappear中調用,這樣當類需要被回收的時候就可以正常進入dealloc中了。

7. 調用一個類的靜態方法需不需要release?

靜態方法,就是類方法,不需要,類方法對象放在autorelease中

8. static作用?

(1)函數體內 static 變數的作用範圍為該函數體,不同於 auto 變數,該變數的記憶體只被分配一次,因此其值在下次調用時仍維持上次的值;

(2)在模組內的 static 全域變數可以被模組內所用函數訪問,但不能被模組外其它函數訪問;

(3)在模組內的 static 函數只可被這一模組內的其它函數調用,這個函數的使用範圍被限制在聲明

它的模組內;

(4)在類中的 static 成員變數屬於整個類所擁有,對類的所有對象只有一份拷貝;

(5)在類中的 static 成員函數屬於整個類所擁有,這個函數不接收 this 指標,因而只能訪問類的static 成員變數。

9. NSObject的load和initialize方法

load和initialize的共同特點:

在不考慮開發人員主動使用的情況下,系統最多會調用一次

如果父類和子類都被調用,父類的調用一定在子類之前

都是為了應用運行提前建立合適的運行環境

在使用時都不要過重地依賴於這兩個方法,除非真正必要

load和initialize的區別:

  • load方法

調用時機比較早,運行環境有不確定因素。具體說來,在iOS上通常就是App啟動時進行載入,但當load調用的時候,並不能保證所有類都載入完成且可用,必要時還要自己負責做auto release處理。對於有依賴關係的兩個庫中,被依賴的類的load會優先調用。但在一個庫之內,調用順序是不確定的。

對於一個類而言,沒有load方法實現就不會調用,不會考慮對NSObject的繼承。

一個類的load方法不用寫明[super load],父類就會收到調用,並且在子類之前。

Category的load也會收到調用,但順序上在主類的load調用之後。

不會直接觸發initialize的調用。

  • initialize方法相關要點

initialize的自然調用是在第一次主動使用當前類的時候。

在initialize方法收到調用時,運行環境基本健全。

initialize的運行過程中是能保證安全執行緒的。

和load不同,即使子類不實現initialize方法,會把父類的實現繼承過來調用一遍。注意的是在此之前,父類的方法已經被執行過一次了,同樣不需要super調用。

由於initialize的這些特點,使得其應用比load要略微廣泛一些。可用來做一些初始化工作,或者單例模式的一種實現方案。

10. 能否向編譯後得到的類中增加執行個體變數?能否向運行時建立的類中添加執行個體變數?為什嗎?

不能向編譯後得到的類中增加執行個體變數;

能向運行時建立的類中添加執行個體變數;

因為編譯後的類已經註冊在 runtime 中,類結構體中的 objc_ivar_list 執行個體變數的鏈表 和 instance_size 執行個體變數的記憶體大小已經確定,同時runtime 會調用 class_setIvarLayout 或 class_setWeakIvarLayout 來處理 strong weak 引用。所以不能向存在的類中添加執行個體變數;

運行時建立的類是可以添加執行個體變數,調用 class_addIvar 函數。但是得在調用 objc_allocateClassPair 之後,objc_registerClassPair 之前,原因同上。

[轉]那些著名或非著名的iOS面試題(下)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.