感覺好的面試題我會攆出來州弟,只需要熟悉過過眼的面試題瓜挽,直接點開鏈接看即可晨抡。
不想浪費太多時間研究派昧,可以直接把這幾套題刷了
iOS面試題總結
iOS面試題匯總
iOS面試葵花寶典
===什么是事件響應鏈,點擊屏幕時是如何互動的剃浇,事件的傳遞===
事件響應鏈
對于IOS設備用戶來說巾兆,他們操作設備的方式主要有三種:觸摸屏幕猎物、晃動設備、通過遙控設施控制設備臼寄。對應的事件類型有以下三種:
1霸奕、觸屏事件(Touch Event)
2、運動事件(Motion Event)
3吉拳、遠端控制事件(Remote-Control Event)
響應者鏈(Responder Chain)
響應者對象(Responder Object),指的是有響應和處理事件能力的對象适揉。響應者鏈就是由一系列的響應者對象構成的一個層次結構留攒。
UIResponder是所有響應對象的基類,在UIResponder類中定義了處理上述各種事件的接口嫉嘀。我們熟悉的UIApplication炼邀、 UIViewController、UIWindow和所有繼承自UIView的UIKit類都直接或間接的繼承自UIResponder剪侮,所以它們的實例都是可以構成響應者鏈的響應者對象拭宁。
響應者鏈有以下特點:
1、響應者鏈通常是由視圖(UIView)構成的瓣俯;
2杰标、一個視圖的下一個響應者是它視圖控制器(UIViewController)(如果有的話),然后再轉給它的父視圖(Super View)彩匕;
3腔剂、視圖控制器(如果有的話)的下一個響應者為其管理的視圖的父視圖;
4驼仪、單例的窗口(UIWindow)的內容視圖將指向窗口本身作為它的下一個響應者
需要指出的是掸犬,Cocoa Touch應用不像Cocoa應用,它只有一個UIWindow對象绪爸,因此整個響應者鏈要簡單一點湾碎;
5、單例的應用(UIApplication)是一個響應者鏈的終點奠货,它的下一個響應者指向nil介褥,以結束整個循環(huán)。
點擊屏幕時是如何互動的
iOS系統(tǒng)檢測到手指觸摸(Touch)操作時會將其打包成一個UIEvent對象仇味,并放入當前活動Application的事件隊列呻顽,單例的UIApplication會從事件隊列中取出觸摸事件并傳遞給單例的UIWindow來處理,UIWindow對象首先會使用hitTest:withEvent:方法尋找此次Touch操作初始點所在的視圖(View)丹墨,即需要將觸摸事件傳遞給其處理的視圖廊遍,這個過程稱之為hit-test view。
UIWindow實例對象會首先在它的內容視圖上調用hitTest:withEvent:贩挣,此方法會在其視圖層級結構中的每個視圖上調用pointInside:withEvent:(該方法用來判斷點擊事件發(fā)生的位置是否處于當前視圖范圍內喉前,以確定用戶是不是點擊了當前視圖)没酣,如果pointInside:withEvent:返回YES,則繼續(xù)逐級調用卵迂,直到找到touch操作發(fā)生的位置裕便,這個視圖也就是要找的hit-test view。
hitTest:withEvent:方法的處理流程如下:首先調用當前視圖的pointInside:withEvent:方法判斷觸摸點是否在當前視圖內见咒;若返回NO,則hitTest:withEvent:返回nil;若返回YES,則向當前視圖的所有子視圖(subviews)發(fā)送hitTest:withEvent:消息偿衰,所有子視圖的遍歷順序是從最頂層視圖一直到到最底層視圖,即從subviews數組的末尾向前遍歷改览,直到有子視圖返回非空對象或者全部子視圖遍歷完畢下翎;若第一次有子視圖返回非空對象,則hitTest:withEvent:方法返回此對象宝当,處理結束视事;如所有子視圖都返回非,則hitTest:withEvent:方法返回自身(self)庆揩。
事件的傳遞和響應分兩個鏈:
傳遞鏈:由系統(tǒng)向離用戶最近的view傳遞俐东。UIKit –> active app’s event queue –> window –> root view –>……–>lowest view
響應鏈:由離用戶最近的view向系統(tǒng)傳遞。initial view –> super view –> …..–> view controller –> window –> Application
===Run Loop是什么订晌,使用的目的虏辫,何時使用和關注點===
Run Loop是一讓線程能隨時處理事件但不退出的機制。RunLoop 實際上是一個對象腾仅,這個對象管理了其需要處理的事件和消息乒裆,并提供了一個入口函數來執(zhí)行Event Loop 的邏輯。線程執(zhí)行了這個函數后推励,就會一直處于這個函數內部 “接受消息->等待->處理” 的循環(huán)中鹤耍,直到這個循環(huán)結束(比如傳入 quit 的消息),函數返回验辞。讓線程在沒有處理消息時休眠以避免資源占用稿黄、在有消息到來時立刻被喚醒。
OSX/iOS 系統(tǒng)中跌造,提供了兩個這樣的對象:NSRunLoop 和 CFRunLoopRef杆怕。CFRunLoopRef 是在 CoreFoundation 框架內的,它提供了純 C 函數的 API壳贪,所有這些 API 都是線程安全的陵珍。NSRunLoop 是基于 CFRunLoopRef 的封裝,提供了面向對象的 API违施,但是這些 API 不是線程安全的互纯。
線程和 RunLoop 之間是一一對應的,其關系是保存在一個全局的 Dictionary 里磕蒲。線程剛創(chuàng)建時并沒有 RunLoop留潦,如果你不主動獲取只盹,那它一直都不會有。RunLoop 的創(chuàng)建是發(fā)生在第一次獲取時兔院,RunLoop 的銷毀是發(fā)生在線程結束時殖卑。你只能在一個線程的內部獲取其 RunLoop(主線程除外)。
系統(tǒng)默認注冊了5個Mode:
kCFRunLoopDefaultMode: App的默認 Mode坊萝,通常主線程是在這個 Mode 下運行的孵稽。
UITrackingRunLoopMode: 界面跟蹤 Mode,用于 ScrollView 追蹤觸摸滑動十偶,保證界面滑動時不受其他 Mode 影響肛冶。
UIInitializationRunLoopMode: 在剛啟動 App 時第進入的第一個 Mode,啟動完成后就不再使用扯键。
GSEventReceiveRunLoopMode: 接受系統(tǒng)事件的內部 Mode,通常用不到珊肃。
kCFRunLoopCommonModes: 這是一個占位的 Mode荣刑,沒有實際作用。
Run Loop的四個作用:
使程序一直運行接受用戶輸入
決定程序在何時應該處理哪些Event
調用解耦
節(jié)省CPU時間
主線程的run loop默認是啟動的伦乔。iOS的應用程序里面厉亏,程序啟動后會有一個如下的main() 函數:
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([appDelegate class]) );
}
}
重點是UIApplicationMain() 函數,這個方法會為main thread 設置一個NSRunLoop 對象烈和,這就解釋了本文開始說的為什么我們的應用可以在無人操作的時候休息爱只,需要讓它干活的時候又能立馬響應。
對其它線程來說招刹,run loop默認是沒有啟動的恬试,如果你需要更多的線程交互則可以手動配置和啟動,如果線程只是去執(zhí)行一個長時間的已確定的任務則不需要疯暑。在任何一個Cocoa程序的線程中幽歼,都可以通過:
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
來獲取到當前線程的run loop鹦牛。
一個run loop就是一個事件處理循環(huán),用來不停的監(jiān)聽和處理輸入事件并將其分配到對應的目標上進行處理。
NSRunLoop是一種更加高明的消息處理模式绞吁,他就高明在對消息處理過程進行了更好的抽象和封裝,這樣才能是的你不用處理一些很瑣碎很低層次的具體消息的處理绍些,在NSRunLoop中每一個消息就被打包在input source或者是timer source中了可训。使用run loop可以使你的線程在有工作的時候工作,沒有工作的時候休眠甘凭,這可以大大節(jié)省系統(tǒng)資源稀拐。
RunLoop
什么時候使用run loop
僅當在為你的程序創(chuàng)建輔助線程的時候,你才需要顯式運行一個run loop对蒲。Run loop是程序主線程基礎設施的關鍵部分钩蚊。所以贡翘,Cocoa和Carbon程序提供了代碼運行主程序的循環(huán)并自動啟動run loop。IOS程序中UIApplication的run方法(或Mac OS X中的NSApplication)作為程序啟動步驟的一部分砰逻,它在程序正常啟動的時候就會啟動程序的主循環(huán)鸣驱。類似的,RunApplicationEventLoop函數為Carbon程序啟動主循環(huán)蝠咆。如果你使用xcode提供的模板創(chuàng)建你的程序踊东,那你永遠不需要自己去顯式的調用這些例程。
對于輔助線程刚操,你需要判斷一個run loop是否是必須的闸翅。如果是必須的,那么你要自己配置并啟動它菊霜。你不需要在任何情況下都去啟動一個線程的run loop坚冀。比如,你使用線程來處理一個預先定義的長時間運行的任務時鉴逞,你應該避免啟動run loop记某。Run loop在你要和線程有更多的交互時才需要,比如以下情況:
使用端口或自定義輸入源來和其他線程通信
使用線程的定時器
Cocoa中使用任何performSelector…的方法
使線程周期性工作
關注點
Cocoa中的NSRunLoop類并不是線程安全的
我們不能再一個線程中去操作另外一個線程的run loop對象构捡,那很可能會造成意想不到的后果液南。不過幸運的是CoreFundation中的不透明類CFRunLoopRef是線程安全的,而且兩種類型的run loop完全可以混合使用勾徽。Cocoa中的NSRunLoop類可以通過實例方法:
- (CFRunLoopRef)getCFRunLoop;
獲取對應的CFRunLoopRef類滑凉,來達到線程安全的目的。
Run loop的管理并不完全是自動的喘帚。
我們仍必須設計線程代碼以在適當的時候啟動run loop并正確響應輸入事件畅姊,當然前提是線程中需要用到run loop。而且啥辨,我們還需要使用while/for語句來驅動run loop能夠循環(huán)運行涡匀,下面的代碼就成功驅動了一個run loop:
BOOL isRunning = NO;
do {
isRunning = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDatedistantFuture]];`
} while (isRunning);
Run loop同時也負責autorelease pool的創(chuàng)建和釋放。
在使用手動的內存管理方式的項目中溉知,會經常用到很多自動釋放的對象陨瘩,如果這些對象不能夠被即時釋放掉,會造成內存占用量急劇增大级乍。Run loop就為我們做了這樣的工作舌劳,每當一個運行循環(huán)結束的時候,它都會釋放一次autorelease pool玫荣,同時pool中的所有自動釋放類型變量都會被釋放掉甚淡。
===ARC和MRC===
Objective-c中提供了兩種內存管理機制MRC(MannulReference Counting)和ARC(Automatic Reference Counting),分別提供對內存的手動和自動管理捅厂,來滿足不同的需求贯卦。Xcode 4.1及其以前版本沒有ARC资柔。
在MRC的內存管理模式下,與對變量的管理相關的方法有:retain,release和autorelease撵割。retain和release方法操作的是引用記數贿堰,當引用記數為零時,便自動釋放內存啡彬。并且可以用NSAutoreleasePool對象羹与,對加入自動釋放池(autorelease調用)的變量進行管理,當drain時回收內存庶灿。
(1) retain纵搁,該方法的作用是將內存數據的所有權附給另一指針變量,引用數加1往踢,即retainCount+= 1;
(2) release腾誉,該方法是釋放指針變量對內存數據的所有權,引用數減1峻呕,即retainCount-= 1;
(3) autorelease妄辩,該方法是將該對象內存的管理放到autoreleasepool中。
在ARC中與內存管理有關的標識符山上,可以分為變量標識符和屬性標識符,對于變量默認為__strong英支,而對于屬性默認為unsafe_unretained佩憾。也存在autoreleasepool。
其中assign/retain/copy與MRC下property的標識符意義相同干花,strong類似與retain,assign類似于unsafe_unretained妄帘,strong/weak/unsafe_unretained與ARC下變量標識符意義相同,只是一個用于屬性的標識池凄,一個用于變量的標識(帶兩個下劃短線__)抡驼。所列出的其他的標識符與MRC下意義相同。
[面試/網絡] TCP/IP:數據鏈路層致盟、IP協(xié)議以及IP協(xié)議相關技術