1. 多線程的底層實現? 2. 線程間怎麼通信? 3. 網路圖片處理問題中怎麼解決一個相同的網路地址重覆請求的問題? 4. 用NSOpertion和NSOpertionQueue處理A,B,C三個線程,要求執行完A,B後才能執行C,怎麼做? 5. 列舉cocoa中常見對幾種多線程的實現,並談談多線程 ...
1. 多線程的底層實現?
1. 首先搞清楚什麼是線程、什麼是多線程
2. Mach是第一個以多線程方式處理任務的系統,因此多線程的底層實現機制是基於Mach的線程
3. 開發中很少用Mach級的線程,因為Mach級的線程沒有提供多線程的基本特征,線程之間是獨立的
4. 開發中實現多線程的方案
C語言的POSIX介面:#include <pthread.h>
OC的NSThread
C語言的GCD介面(性能最好,代碼更精簡)
OC的NSOperation和NSOperationQueue(基於GCD)
2. 線程間怎麼通信?
1. performSelector:onThread:withObject:waitUntilDone:
2. NSMachPort
3. 網路圖片處理問題中怎麼解決一個相同的網路地址重覆請求的問題?
利用字典(圖片地址為key,下載操作為value),具體可以查看SD緩存機制
4. 用NSOpertion和NSOpertionQueue處理A,B,C三個線程,要求執行完A,B後才能執行C,怎麼做?
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSOperation *A = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"SuperLog------ NSOperationA");
}];
NSOperation *B = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"SuperLog------ NSOperationB");
}];
NSOperation *C = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"SuperLog------ NSOperationC");
}];
[C addDependency:A];
[C addDependency:B];
[queue addOperation:A];
[queue addOperation:B];
[queue addOperation:C];
5. 列舉cocoa中常見對幾種多線程的實現,並談談多線程安全的幾種解決辦法及多線程安全怎麼控制?
1. 只在主線程刷新訪問UI
2. 如果要防止資源搶奪,得用synchronized進行加鎖保護
3. 如果非同步操作要保證線程安全等問題, 儘量使用GCD(有些函數預設就是安全的)
6. GCD內部怎麼實現的?
1. iOS和OS X的核心是XNU內核,GCD是基於XNU內核實現的
2. GCD的API全部在libdispatch庫中
3. GCD的底層實現主要有Dispatch Queue和Dispatch Source
Dispatch Queue :管理block(操作)
Dispatch Source :處理事件
7. 你用過NSOperationQueue麽?如果用過或者瞭解的話,你為什麼要使用NSOperationQueue,實現了什麼?請描述它和GCD的區別和類似的地方(提示:可以從兩者的實現機制和適用範圍來描述)。
1. GCD是純C語言的API,NSOperationQueue是基於GCD的OC版本封裝
2. GCD只支持FIFO的隊列,NSOperationQueue可以很方便地調整執行順序、設置最大併發數量
3. NSOperationQueue可以在輕鬆在Operation間設置依賴關係,而GCD需要寫很多的代碼才能實現
4. NSOperationQueue支持KVO,可以監測operation是否正在執行(isExecuted)、是否結束(isFinished),是否取消(isCanceld)
5. GCD的執行速度比NSOperationQueue快
任務之間不太互相依賴:GCD
任務之間有依賴\或者要監聽任務的執行情況:NSOperationQueue
8. 既然提到GCD,那麼問一下在使用GCD以及block時要註意些什麼?它們兩是一回事兒嗎?block在ARC中和傳統的MRC中的行為和用法有沒有什麼區別,需要註意些什麼?
Block的使用註意:
1. block的記憶體管理
2. 防止迴圈retian
非ARC(MRC):__block
ARC:__weak\__unsafe_unretained
9. 在非同步線程中下載很多圖片,如果失敗了,該如何處理?請結合RunLoop來談談解決方案.(提示:在非同步線程中啟動一個RunLoop重新發送網路請求,下載圖片)。
1. 重新下載圖片
2. 下載完畢, 利用RunLoop的輸入源回到主線程刷新UIImageView
10. 怎麼保證多人開發進行記憶體泄露的檢查?
1. 使用Analyze進行代碼的靜態分析
2. 儘量使用ARC
11. 非自動記憶體管理情況下怎麼做單例模式?
創建單例設計模式的基本步驟:
1. 聲明一個單件對象的靜態實例,並初始化為nil
2. 創建一個類的類工廠方法,當且僅當這個類的實例為nil時生成一個該類的實例
3. 實現NScopying協議, 覆蓋allocWithZone:方法,確保用戶在直接分配和初始化對象時,不會產生另一個對象
4. 覆蓋release、autorelease、retain、retainCount方法, 以此確保單例的狀態。
5. 在多線程的環境中,註意使用@synchronized關鍵字或GCD,確保靜態實例被正確的創建和初始化。
12. 對於類方法(靜態方法)預設是autorelease的,所有類方法都會這樣嗎?
1. 系統自帶的絕大數類方法返回的對象,都是經過autorelease的
13. block在ARC中和MRC中的用法有什麼區別,需要註意什麼?
1. 對於沒有引用外部變數的Block,無論在ARC還是非ARC下,類型都是__NSGlobalBlock__,這種類型的block可以理解成一種全局的block,不需要考慮作用域問題。同時,對他進行Copy或者Retain操作也是無效的
2. 應註意避免迴圈引用
14. 什麼情況下會發生記憶體泄漏和記憶體溢出?
1. 當程式在申請記憶體後,無法釋放已申請的記憶體空間(例如一個對象或者變數使用完成後沒有釋放,這個對象一直占用著記憶體),一次記憶體泄露危害可以忽略,但記憶體泄露堆積後果很嚴重,無論多少記憶體,遲早會被占光。記憶體泄露會最終會導致記憶體溢出!
2. 當程式在申請記憶體時,沒有足夠的記憶體空間供其使用,出現out of memory;比如申請了一個int,但給它存了long才能存下的數,那就是記憶體溢出。
15. [NSArray arrayWithobject:(id)obj]
這個方法添加對象後,需要對這個數組做釋放操作嗎?
不需要這個對象被放到自動釋放池中
16. 自動釋放池底層怎麼實現?
自動釋放池以棧的形式實現:當你創建一個新的自動釋放池時,它將被添加到棧頂。當一個對象收到發送autorelease消息時,它被添加到當前線程的處於棧頂的自動釋放池中,當自動釋放池被回收時,它們從棧中被刪除, 並且會給池子裡面所有的對象都會做一次release操作.
17. KVO內部實現原理是什麼?
1. KVO是基於runtime機制實現的
2. 當某個類的對象第一次被觀察時,系統就會在運行期動態地創建該類的一個派生類,在這個派生類中重寫基類中任何被觀察屬性的setter方法。
3. 派生類在被重寫的 setter 方法實現真正的通知機制(NSKVONotifying_Class)
18. 是否可以把比較耗時的操作放在NSNotificationCenter中?
如果在非同步線程發的通知,那麼可以執行比較耗時的操作
如果在主線程發的通知,那麼就不可以執行比較耗時的操作
19. Foundation對象與Core Foundation對象有什麼區別?
1. Foundation對象是OC的,Core Foundation對象是C對象
2. 數據類型之間的轉換
ARC:__bridge_retained、__bridge_transfer
非ARC: __bridge
20. 如何不用中間變數,用兩種方法交換A和B的值?
A = A + B
B = A - B
A = A - B
A = A^B;
B = A^B;
A = A^B;
21. 簡單描述下對單利模式設計的理解?
節省記憶體資源,一個應用就一個對象。
22. runtime實現的機制是什麼,如何用,用來做什麼?你所使用的相關的頭文件或者某些方法的名稱有哪些?
運行時機制,runtime庫裡面包含了跟類、成員變數、方法相關的API,比如獲取類裡面的所有成員變數,為類動態添加成員變數,動態改變類的方法實現,為類動態添加新的方法等 需要導入<objc/message.h> <objc/runtime.h>
1. runtime,運行時機制,它是一套C語言庫
2. 實際上我們編寫的所有OC代碼,最終都是轉成了runtime庫的東西,比如類轉成了runtime庫裡面的結構體等數據類型,方法轉成了runtime庫裡面的C語言函數,平時調方法都是轉成了objc_msgSend函數(所以說OC有個消息發送機制)。因此,可以說runtime是OC的底層實現,是OC的幕後執行者
3. 有了runtime庫,能做什麼事情呢?runtime庫裡面包含了跟類、成員變數、方法相關的API,比如獲取類裡面的所有成員變數,為類動態添加成員變數,動態改變類的方法實現,為類動態添加新的方法等。因此,有了runtime,想怎麼改就怎麼改
23. 是否使用Core Text或者Core Image等?如果使用過,請談談你使用Core Text或者Core Image的體驗。
CoreText
1. 隨意修改文本的樣式
2. 圖文混排(純C語言)
3. 國外:Niumb
Core Image(濾鏡處理)
- 能調節圖片的各種屬性(對比度, 色溫, 色差等)
24. NSNotification和KVO的區別和用法是什麼?什麼時候應該使用通知,什麼時候應該使用KVO,它們的實現上有什麼區別嗎?如果用protocol和delegate(或者delegate的Array)來實現類似的功能可能嗎?如果可能,會有什麼潛在的問題?如果不能,為什麼?(雖然protocol和delegate這種東西面試已經面爛了…)?
通知比較靈活(1個通知能被多個對象接收, 1個對象能接收多個通知)
代理比較規範,但是代碼多(預設是1對1)
KVO性能不好(底層會動態產生新的類),只能監聽某個對象屬性的改變, 不推薦使用(1個對象的屬性能被多個對象監聽,1個對象能監聽多個對象的其他屬性)
更詳細參考:
25. Block內部的實現原理
Objective-C是對C語言的擴展,block的實現是基於指針和函數指針
26. 有兩個數組a和b,大小都為n,通過交換a,b中的元素,使sum(a)-sum(b)最小
演算法題,百度自己學習。
思路
1. 計算 differ = sum(a) - sum(b)
2. 尋找 a b 數組中差值最接近differ/2 的元素
3. 交換元素
27. 如果後期需要增加資料庫中的欄位怎麼實現,如果不使用CoreData呢?
編寫SQL語句來操作原來表中的欄位
1. 增加表欄位
ALTER TABLE 表名 ADD COLUMN 欄位名 欄位類型;
2. 刪除表欄位
ALTER TABLE 表名 DROP COLUMN 欄位名;
3. 修改表欄位
ALTER TABLE 表名 RENAME COLUMN 舊欄位名 TO 新欄位名;
28. SQLite數據存儲是怎麼用?
1. 添加SQLite動態庫
2. 導入主頭文件:#import <sqlite3.h>
3. 利用C語言函數創建/打開資料庫,編寫SQL語句
29. 簡單描述下客戶端的緩存機制?
1. 緩存可以分為:記憶體數據緩存、資料庫緩存、文件緩存
2. 每次想獲取數據的時候
2.1 先檢測記憶體中有無緩存
2.2 再檢測本地有無緩存(資料庫\文件)
2.3 最終發送網路請求
2.4 將伺服器返回的網路數據進行緩存(記憶體、資料庫、文件),以便下次讀取
30. 你實現過多線程的Core Data麽?NSPersistentStoreCoordinator,NSManagedObjectContext和NSManagedObject中的哪些需要線上程中創建或者傳遞?你是用什麼樣的策略來實現的?
1. CoreData是對SQLite資料庫的封裝
2. CoreData中的NSManagedObjectContext在多線程中不安全
3. 如果想要多線程訪問CoreData的話,最好的方法是一個線程一個NSManagedObjectContext
4. 每個NSManagedObjectContext對象實例都可以使用同一個NSPersistentStoreCoordinator實例,這是因為NSManagedObjectContext會在便用NSPersistentStoreCoordinator前上鎖
31. Core Data數據遷移
32. 怎麼解決緩存池滿的問題(cell)
ios中不存在緩存池滿的情況,因為通常我們ios中開發,對象都是在需要的時候才會創建,有種常用的說話叫做懶載入,還有在UITableView中一般只會創建剛開始出現在屏幕中的cell,之後都是從緩存池裡取,不會在創建新對象。緩存池裡最多也就一兩個對象,緩存池滿的這種情況一般在開發java中比較常見,java中一般把最近最少使用的對象先釋放。
33. CAAnimation的層級結構
Core Animation Programming Guide
graph TB A(CAAnimation) --> B1(CAPropertyAnimation) A --> B2(CAAnimationGroup) A --> B3(CATransition) B1 --> C1(CABasicAnimation) B1 --> C2(CAKeyframeAnimation) C1 --> D(CASpringAnimation)34. 按鈕或者其它UIView控制項的事件傳遞的具體過程
如何找到最合適的視圖
1. 自己是否能接收觸摸事件
2. 觸摸點是否在自己身上
3. 從後往前遍歷子控制項,重覆前面的兩個步驟
4. 如果沒有符合條件的子控制項,那麼自己最適合處理
35. 控制器View的生命周期及相關函數是什麼?你在開發中是如何用的?
1. 首先判斷控制器是否有視圖,如果沒有就調用loadView方法創建(storyboard/代碼)
2. 隨後調用viewDidLoad,可以進行下一步的初始化操作(只會被調用一次)
3. 在視圖顯示之前調用viewWillAppear(該函數可以多次調用)
4. viewDidAppear
3. 在視圖顯示之前調用viewWillDisappear;該函數可以多次調用(如需要)
5. 在佈局變化前後,調用viewWill/DidLayoutSubviews處理相關信息
36. NSRunLoop的實現機制,及在多線程中如何使用?
NSRunLoop是iOS消息機制的處理模式
1. NSRunLoop的主要作用:控制NSRunLoop裡面線程的執行和休眠,在有事情做的時候使當前NSRunLoop控制的線程工作,沒有事情做讓當前NSRunLoop的控制的線程休眠。
2. NSRunLoop 就是一直在迴圈檢測,從線程start到線程end,檢測inputsource(如點擊,雙擊等操作)非同步事件,檢測timesource同步事件,檢測到輸入源會執行處理函數,首先會產生通知,corefunction向線程添加runloop observers來監聽事件,意在監聽事件發生時來做處理。
3. runloopmode是一個集合,包括監聽:事件源,定時器,以及需通知的runloop observers
多線程中如何使用?
1. 只有在為你的程式創建次線程的時候,才需要運行run loop。對於程式的主線程而言,run loop是關鍵部分。Cocoa提供了運行主線程run loop的代碼同時也會自動運行run loop。iOS程式UIApplication中的run方法在程式正常啟動的時候就會啟動run loop。如果你使用xcode提供的模板創建的程式,那你永遠不需要自己去啟動run loop
2. 在多線程中,你需要判斷是否需要run loop。如果需要run loop,那麼你要負責配置run loop並啟動。你不需要在任何情況下都去啟動run loop。比如,你使用線程去處理一個預先定義好的耗時極長的任務時,你就可以毋需啟動run loop。Run loop只在你要和線程有交互時才需要
37. iOS7之前,後臺執行內容有幾種形式,都是什麼?
一般的應用在進入後臺的時候可以獲取一定時間來運行相關任務,也就是說可以在後臺運行一小段時間(10S左右)。
1. 後臺播放音樂
2. 後臺GPS跟蹤
3. 後臺voip支持
38. 簡單說一下APP的啟動過程,從main文件開始說起
程式啟動分為兩類:
1. 有storyboard
2. 沒有storyboard
情況一:
1.main函數
2.UIApplicationMain
* 創建UIApplication對象
* 創建UIApplication的delegate對象
3.根據Info.plist獲得最主要storyboard的文件名,載入最主要的storyboard(有storyboard)
* 創建UIWindow
* 創建和設置UIWindow的rootViewController
* 顯示視窗
情況二:
1.main函數
2.UIApplicationMain
* 創建UIApplication對象
* 創建UIApplication的delegate對象
3.delegate對象開始處理(監聽)系統事件(沒有storyboard)
* 程式啟動完畢的時候, 就會調用代理的application:didFinishLaunchingWithOptions:方法
* 在application:didFinishLaunchingWithOptions:中創建UIWindow
* 創建和設置UIWindow的rootViewController
* 顯示視窗
39. 把程式自己關掉和程式進入後臺,遠程推送的區別?
1. 關掉後不執行任何代碼,不能處理事件
2. 應用程式進入後臺狀態不久後轉入掛起狀態。在這種狀態下,應用程式不執行任何代碼,並有可能在任意時候從記憶體中刪除。只有當用戶再次運行此應用,應用才會從掛起狀態喚醒,代碼得以繼續執行
3. 或者進入後臺時開啟多任務狀態,保留在記憶體中,這樣就可以執行系統允許的動作
4. 遠程推送是由遠程伺服器上的程式發送到APNS,再由APNS把消息推送至設備上的程式,當應用程式收到推送的消息會自動調用特定的方法執行事先寫好的代碼
5. 本地通知和遠程推送通知對基本概念和用法?
* 本地通知和遠程推送通知都可以向不在前臺運行的應用發送消息,這種消息既可能是即將發生的事件,也可能是伺服器的新數據.不管是本地通知還是遠程通知,他們在程式界面的顯示效果相同,都可能顯示為一段警告信息或應用程式圖標上的微章.
* 本地通知和遠程推送通知的基本目的都是讓應用程式能夠通知用戶某些事情,而且不需要應用程式在前臺運行.二者的區別在於本地通知由本應用負責調用,只能從當前設備上的iOS發出, 而遠程通知由遠程伺服器上的程式發送到APNS,再由APNS把消息推送至設備上的程式
40. SIP是什麼?
1. SIP(Session Initiation Protocol),會話發起協議
2. SIP是建立VOIP連接的 IETF 標準,IETF是全球互聯網最具權威的技術標準化組織
3. 所謂VOIP,就是網路電話,直接用互聯網打電話,不用耗手機話費
41. 有些圖片載入的比較慢怎麼處理?你是怎麼優化程式的性能的?
1. 圖片下載放在非同步線程
2. 圖片下載過程中使用占點陣圖片
3. 如果圖片較大,可以考慮多線程斷點下載
42. 你實現過一個框架或者庫以供別人使用麽?如果有,請談一談構建框架或者庫時候的經驗;如果沒有,請設想和設計框架的public的API,並指出大概需要如何做,需要註意一些什麼方面,來使別人容易地使用你的框架。
1. 提供給外界的介面功能是否實用、夠用
2. 能不能根據類名、方法名就猜出介面的具體作用
3. 提供的參數是否夠用、調用起來是否簡單
4. 要不要再導入依賴其他的框架
43. App需要載入超大量的數據,給伺服器發送請求,但是伺服器卡住瞭如何解決?
1. 設置請求超時
2. 給用戶提示請求超時
3. 根據用戶操作再次請求數據
44. 利用NSNotificationCenter實現跨多控制器傳輸數據和消息中用同步還是非同步?
1. 如果通知是在主線程發出,那麼接收通知的方法中的耗時操作要放到非同步線程中
2. 如果通知實在非同步線程中發出,那麼接收通知後調用的方法會預設在非同步線程中執行
45. SDWebImage具體如何實現?
1. 利用NSOperationQueue和NSOperation下載圖片, 還使用了GCD的一些函數(解碼GIF圖片)
2. 利用URL作為key,NSOperation作為value
3. 利用URL作為key,UIImage作為value
待完善...
46. AFN 與 ASI 有什麼區別
1. AFN基於NSURL,ASI基於底層的CFNetwork框架,因此ASI的性能優於AFN
2. AFN採取block的方式處理請求,ASI最初採取delegate的方式處理請求,後面也增加了block的方式
3. AFN只封裝了一些常用功能,滿足基本需求,直接忽略了很多擴展功能,比如沒有封裝同步請求;ASI提供的功能較多,預留了各種介面和工具供開發者自行擴展
4. AFN直接解析伺服器返回的JSON、XML等數據,而ASI比較原始,返回的是NSData二進位數據
47. Runloop定時源和輸入源
1. 你創建的程式不需要顯示的創建run loop;每個線程,包括程式的主線程(main thread)都有與之相應的run loop對象, 主線程會自行創建並運行run loop
2. Runloop處理的輸入事件有兩種不同的來源:輸入源(input source)和定時源(timer source)
3. 輸入源傳遞非同步消息,通常來自於其他線程或者程式。定時源則傳遞同步消息,在特定時間或者一定的時間間隔發生
48. 如果在網路數據處理過程中,發現一處比較卡,一般怎麼解決
1. 檢查網路請求操作是否被放在主線程了
2. 看看非同步請求的數量是否太多了(子線程數量)
3. 數據量是否太大?如果太大,先清除一些不必要的對象(看不見的數據、圖片)
4. 手機CPU使用率和記憶體問題
49. 怎麼解決sqlite鎖定的問題
1. 設置資料庫鎖定的處理函數
int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
2. 設定鎖定時的等待時間
int sqlite3_busy_timeout(sqlite3*, 60);