你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 【面試】iOS 開發面試題(三)

【面試】iOS 開發面試題(三)

編輯:IOS開發綜合

1、iOS數據持久化存儲方案有哪些?

參考答案:

plist屬性列表存儲(如NSUserDefaults) 文件存儲(如二進制數據寫入文件存儲,通過NSFileManager來操作將下載起來的二進制數據寫一篇文件中存儲) NSKeydeArchiver歸檔存儲,常見的是自動化歸檔/解檔處理,想要學習如何通過runtime實現自動化歸檔/解檔,可 數據庫SQLite3存儲(如FMDB、Core Data)

2、沙盒的目錄結構是怎樣的?各自一般用於什麼場合?

參考答案:

Application:存放程序源文件,上架前經過數字簽名,上架後不可修改 Documents: 保存應?運行時生成的需要持久化的數據,iTunes同步設備時會備份該目 錄。例如,游戲應用可將游戲存檔保存在該目錄 tmp: 保存應?運行時所需的臨時數據,使?完畢後再將相應的文件從該目錄刪除。應用 沒有運行時,系統也可能會清除該目錄下的文件。iTunes同步設備時 不會備份該目錄 Library/Caches: 保存應用運行時?成的需要持久化的數據,iTunes同步設備時不會備份 該目錄。?一般存儲體積大、不需要備份的非重要數據,比如網絡數據緩存存儲到Caches下 Library/Preference: 保存應用的所有偏好設置,如iOS的Settings(設置) 應?會在該目錄中查找應?的設置信息。iTunes同步設備時會備份該目錄

3、#define定義的宏和const定義的常量有什麼區別?

參考答案:

#define定義宏的指令,程序在預處理階段將用#define所定義的內容只是進行了替換。因此程序運行時,常量表中並沒有用#define所定義的宏,系統並不為它分配內存,而且在編譯時不會檢查數據類型,出錯的概率要大一些。 const定義的常量,在程序運行時是存放在常量表中,系統會為它分配內存,而且在編譯時會進行類型檢查。 #define定義表達式時要注意“邊緣效應”,例如如下定義:

 

  1 2 3 4 #define N 2 + 3 // 我們預想的N值是5,我們這樣使用N int a = N / 2;// 我們預想的a的值是2.5,可實際上a的值是3.5

4、常見的出現內存循環引用的場景有哪些?

參考答案:

定時器(NSTimer):NSTimer經常會被作為某個類的成員變量,而NSTimer初始化時要指定self為target,容易造成循環引用(self->timer->self)。 另外,若timer一直處於validate的狀態,則其引用計數將始終大於0,因此在不再使用定時器以後,應該先調用invalidate方法 block的使用:block在copy時都會對block內部用到的對象進行強引用(ARC)或者retainCount增1(非ARC)。在ARC與非ARC環境下對block使用不當都會引起循環引用問題, 一般表現為,某個類將block作為自己的屬性變量,然後該類在block的方法體裡面又使用了該類本身,簡單說就是self.someBlock =Type var{[self dosomething];或者self.otherVar = XXX;或者_otherVar = …};出現循環的原因是:self->block->self或者self->block->_ivar(成員變量) 代理(delegate):在委托問題上出現循環引用問題已經是老生常談了,規避該問題的殺手锏也是簡單到哭,一字訣:聲明delegate時請用assign(MRC)或者weak(ARC),千萬別手賤玩一下retain或者strong,畢竟這基本逃不掉循環引用了!

5、block中的weak self,是任何時候都需要加的麼?

參考答案:

不是什麼任何時候都需要添加的,不過任何時候都添加似乎總是好的。只要出現像self->block->self.property/self->_ivar這樣的結構鏈時,才會出現循環引用問題。好好分析一下,就可以推斷出是否會有循環引用問題。

6、GCD的queue、main queue中執行的代碼一定是在main thread麼?

參考答案:

對於queue中所執行的代碼不一定在main thread中。如果queue是在主線程中創建的,那麼所執行的代碼就是在主線程中執行。如果是在子線程中創建的,那麼就不會在main thread中執行。 對於main queue就是在主線程中的,因此一定會在主線程中執行。獲取main queue就可以了,不需要我們創建,獲取方式通過調用方法dispatchgetmain_queue來獲取。

7、頭文件中聲明的成員變量(不是屬性),外部可直接訪問麼?

參考答案:

外部不能直接訪問頭文件所聲明的成員變量,需要提供成員變量的getter方法才能在外部訪問。而屬性已經直接給我們自動生成了getter方法,因此外部可以直接訪問屬性。

8、TCP和UDP的區別是什麼?

參考答案:

TCP:面向連接、傳輸可靠(保證數據正確性,保證數據順序傳輸)、用於傳輸大量數據(流模式)、速度慢,建立連接需要開銷較多(時間,系統資源)。 UDP:面向非連接、傳輸不可靠、用於傳輸少量數據(數據包模式)、速度快,傳輸的是報文。

9、MD5和Base64的區別是什麼,各自使用場景是什麼?

參考答案:

做過加密相關的功能的,幾乎都會使用到MD5和Base64,它們兩者在實際開發中是最常用的。

MD5:是一種不可逆的摘要算法,用於生成摘要,無法逆著破解得到原文。常用的是生成32位摘要,用於驗證數據的有效性。比如,在網絡請求接口中,通過將所有的參數生成摘要,客戶端和服務端采用同樣的規則生成摘要,這樣可以防篡改。又如,下載文件時,通過生成文件的摘要,用於驗證文件是否損壞。 Base64:屬於加密算法,是可逆的,經過encode後,可以decode得到原文。在開發中,有的公司上傳圖片采用的是將圖片轉換成base64字符串,再上傳。在做加密相關的功能時,通常會將數據進行base64加密/解密。

10、發送10個網絡請求,然後再接收到所有回應之後執行後續操作,如何實現?

參考答案:

從題目分析可知,10個請求要全部完成後,才執行某一功能。比如,下載10圖片後合成一張大圖,就需要異步全部下載完成後,才能合並成大圖。

做法:通過dispatch_group_t來實現,將每個請求放入到Group中,將合並成大圖的操作放在dispatch_group_notify中實現。

  1 2 3 4 5 6 7 8 9 10 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{ /*加載圖片1 */ }); dispatch_group_async(group, queue, ^{ /*加載圖片2 */ }); dispatch_group_async(group, queue, ^{ /*加載圖片3 */ }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ // 合並圖片 });

 

11、__block和__weak修飾符的區別?

參考答案:

__block不管是ARC還是MRC模式下都可以使用,它的作用是標識block外的變量在block內使用可以修改變量的值。 __weak只能在ARC模式下使用,表示弱引用,主要是用於防止循環引用而引入的。

12、常見的Http狀態碼有哪些?

參考答案:

302是請求重定向。 500及以上是服務器錯誤,如503表示服務器找不到、3840表示服務器返回無效JSON。 400及以上是請求鏈接錯誤或者找不到服務器,如常見的404。 200及以上是正確,如常見的是200表示請求正常。 100及以上是請求接受成功。

13、iOS與H5交互的方式有哪些?

參考答案:

通過協議在shouldStartRequest中捕獲請求,獲取scheme來判斷預先定義的功能,然後調用native代碼。比如,定義點擊圖片調用native來展示大圖,那麼js接收到點擊時,重定向將圖片的url添加上自定義scheme,如HYBImagePreview://這樣。

14、如何淺拷貝與深拷貝的理解?

參考答案:

所謂淺拷貝是指只復制指向對象的指針,而不復制引用對象本身(同一份內存),而所謂深拷貝是指復制引用對象本身(新創建了一份內存)。

15、使用是懶加載?常見場景?

參考答案:

所謂懶加載是指在真正需要到的時候才真正載入內存。常見的場景就是重寫屬性的getter方法,在getter方法中判斷是否創建過或者加載過,若未創建過或者未加載過,則創建或者加載。

懶加載可以優化性能,有的功能一般情況下不會使用到,但是這些功能一使用就會占較大的內存,此時使用懶加載就非常的好了。

常見的寫法:

  1 2 3 4 5 6 7 8 9 - (NSMutableArray *)dataSource { if (_dataSource == nil) { _dataSource = [[NSMutableArray alloc] init]; // 添加默認數據等 // ... } }

 

16、一個tableView是否可以關聯兩個不同的數據源?

參考答案:

當然是可以關聯多個不同的數據源,但是不同同時使用多個數據源而已。比如,一個列表有兩個篩選功能,一個是篩選城市,一個是篩選時間,那麼這兩個就是兩個數據源了。當篩選城市時,就會使用城市數據源;當篩選時間時,就會使用時間數據源。

17、對象添加到通知中心中,當通知中心發通知時,這個對象卻已經被釋放了,可能會出現什麼問題?

參考答案:

其實這種只是考查對通知的簡單應用。通知是多對多的關系,主要使用場景是跨模塊傳值。當某對象加入到通知中心後,若在對象被銷毀前不將該對象從通知中心中移除,當發送通知時,就會造成崩潰。這是很常見的。所以,在添加到通知中心後,一定要在釋放前移除。

18、實現過框架或者庫以供他人使用麼?如果有,請談一談構建框架或者庫時候的經驗;如果沒有,請設想和設計框架的public的API,並指出大概需要如何做、需要注意哪些問題,以使人人更容易地使用你的框架。

參考答案:

從以下角度出發來思考和設計公共框架:

確保外部調用簡單,且保證有詳細的頭文件注釋說明。 確保API編碼規范,保證風格統一。 確保API易擴展,可以考慮預留參數 確保沒有外部依賴或者依賴要盡可能的少,以保證公共庫的純潔(原則上不能有外部依賴) 確保易維護,不存在冗余API

19、如何自動計算cell的高度?

參考答案:

筆者喜歡純代碼自動布局,一直使用Masonry這個第三方庫來實現純代碼自動布局的,使用起來非常簡單,而且效率也很高。開發起來,提高了開發效率。

關於Masonry自動計算行高,筆者提供了swift版和oc版本的擴展,這兩個版本都提供了自動計算行高的功能,並且帶有緩存功能,保證永遠只計算一次行高,效率就會很高,一般的應用也就不會卡屏了。

實現原理:通過數據模型的id作為key,以確保唯一,如何才能保證復用cell時不會出現混亂。在配置完數據後,通過更新約束,得到最後一個控件的frame,就只可以判斷cell實際需要的高度,並且緩存下來,下次再獲取時,判斷是否存在,若存在則直接返回。因此,只會計算一遍。

20、UITableView是如何計算內容高度的?為什麼初始化時配置數據時,獲取行高的代理方法會調用數據條數次?

參考答案:

UITableView是繼承於UIScrollView的,因此也有contentSize。要得到tableview的contentsize,就需要得到所有cell的高度,從而計算出總高度,才能得到contentsize。因此,在reloadData時,就會調用該代理方法數據條數次。

為了提高效率,筆者寫了擴展用於自動計算行高的,並且帶有緩存,以保證只會計算一次,防止卡屏。做到這一點,一般的應用就可以解決卡屏的問題了。對於富文本比較多的應用,還可以繼續優化哦。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved