2018 - iOS 面試題彙總

陳雨塵發表於2018-07-18

2018 - iOS 面試題彙總

金三銀四,相信最近很多人都在跳槽。那麼面試題自然還是要看下的,在這我就把我手裡收集到的面試題(朋友面試,網上收集等等)進行了彙總,希望可以幫到正在或者準備面試的你,同時我也可以自己在過一遍?

一般面試題

1.堆和棧的區別

1.記憶體管理範圍 只有oc物件需要進行記憶體管理 非oc物件型別比如基本資料型別不需要進行記憶體管理 2.記憶體管理本質 因為:Objective-C的物件在記憶體中是以堆的方式分配空間的,並且堆記憶體是由你釋放的,就是release OC物件存放於堆裡面(堆記憶體要程式設計師手動回收) 非OC物件一般放在棧裡面(棧記憶體會被系統自動回收) 堆裡面的記憶體是動態分配的,所以也就需要程式設計師手動的去新增記憶體、回收記憶體 3.記憶體分配以及管理方式 按分配方式分 堆是動態分配和回收記憶體的,沒有靜態分配的堆 棧有兩種分配方式:靜態分配和動態分配 靜態分配是系統編譯器完成的,比如區域性變數的分配 動態分配是有alloc函式進行分配的,但是棧的動態分配和堆是不同的,它的動態分配也由系統編譯器進行釋放,不需要程式設計師手動管理 按管理方式分 對於棧來講,是由系統編譯器自動管理,不需要程式設計師手動管理 對於堆來講,釋放工作由程式設計師手動管理,不及時回收容易產生記憶體洩露 堆:是大家共有的空間,分全域性堆和區域性堆。全域性堆就是所有沒有分配的空間,區域性堆就是使用者分配的空間。堆在作業系統對程式 初始化的時候分配,執行過程中也可以向系統要額外的堆,但是記得用完了要還給作業系統,要不然就是記憶體洩漏。堆裡面一般 放的是靜態資料,比如static的資料和字串常量等,資源載入後一般也放在堆裡面。一個程式的所有執行緒共有這些堆 ,所以對堆的操作要考慮同步和互斥的問題。程式裡面編譯後的資料段都是堆的一部分。 棧:是個執行緒獨有的,儲存其執行狀態和區域性自動變數的。棧線上程開始的時候初始化,每個執行緒的棧互相獨立,因此 ,棧是 thread safe的。每個c++物件的資料成員也存在在棧中,每個函式都有自己的棧,棧被用來在函式之間傳遞引數。作業系統在切換執行緒的時候會自動的切換棧,就是切換ss/esp暫存器。棧空間不需要在高階語言裡面顯式的分配 和釋放。 一句話總結就是 堆:由程式設計師分配和釋放,如果不釋放可能會引起記憶體洩漏 棧:由編譯器自動分配和釋放,一般存放引數值,區域性變數

2.KVO和KVC

KVC,即是指 NSKeyValueCoding(鍵值編碼),提供一種機制來間接訪問物件的屬性。KVC 就是基於KVO技術來實現的。 KVO,提供了一種觀察者的機制,通過對某個物件的某個屬性新增觀察者,當該屬性改變,就會呼叫"observeValueForKeyPath:"方法。

  1. OC中建立執行緒的方法是什麼?如果在主執行緒中執行程式碼, 方法是什麼?如果想延時執行程式碼、方法是什麼?

1、執行緒建立有三種方法:使用NSThread建立、使用GCD的dispatch、使用子類化的NSOperation,然後將其加入NSOperationQueue; 2、在主執行緒執行程式碼,方法是performSelectorOnMainThread:withObject:waitUntilDone:; 3、如果想延時執行程式碼可以用performSelector:onThread:withObject:waitUntilDone:;

4.指標與陣列名的關係?

int arrayName[4] = {10, 20, 30, 40}; int *p = (int *)(&arrayName + 1); NSLog(@"%d", (&arrayName - 1)); 1.(&arrayName + 1):&arrayName是陣列的地址(等價於指向arrayName陣列的指標) 2.增加 1 會往後移動16個位元組,開始是4個位元組的位置,移動後就是16個位元組後面的位置(也就是目前位置是20個位元組) 3.最後又賦值給,int型別的指標p(int型別佔4個位元組) 4.所以(p - 1)就是減去4個位元組,變成為16個位元組的位置,輸出的(p - 1)值為40 int *p = (int *)(&arrayName + 1); NSLog(@"%d", *(p - 1));//輸出結果為 40

5.#import 和#include有 麼區別?@class呢?#import <>和 #import"" 有 麼區別?

import是OC匯入標頭檔案的關鍵字,#include是C/C++匯入標頭檔案的關鍵字 使用#import只匯入一次不會重複匯入,相當於#include和#pragma once;(使用#include可能會出現迴圈引用,使用#pragma once消除這種可能) @class一般用於宣告某個字串作為類名使用,它只是宣告瞭一個類名,沒有匯入.h檔案中的內容,不會引起交叉編譯問題 import< >代表匯入系統自帶的框架 import" "代表匯入我們自己建立的檔案,匯入的使我們.h檔案,也就是標頭檔案

6.屬性readwrite.readonly,assign,retain,copy,nonatomic 什麼作用 ? 在哪種情況下 ?

readwrite 是可讀可寫特性;需要生成getter方法和setter方法時(補充:預設屬性,將生成不帶額外引數的getter和setter方法(setter方法只有一個引數)) readonly 是隻讀特性 只會生成getter方法 不會生成setter方法 ;不希望屬性在類外改變 assign 是賦值特性,setter方法將傳入引數賦值給例項變數;僅設定變數時; retain 表示持有特性,setter方法將傳入引數先保留,再賦值,傳入引數的retaincount會+1; copy 表示拷貝特性,setter方法將傳入物件複製一份;需要完全一份新的變數時。 nonatomic 非原子操作,決定編譯器生成的setter getter是否是原子操作,atomic表示多執行緒安全,一般使 用nonatomic

7.IBOutlet 連出來的檢視屬性為什麼可以被設定成weak?

在 storyboard 中新增一個控制元件引用關係是這樣的(以 UIbutton 為例): UIviewController -> UIview -> UIbutton 此時 UIviewController 強引用著 UIview , UIview 強引用著 UIbutton , IBoutlet 連線到控制器的. m 或者. h 中作為檢視的屬性時用 weak 修飾就可以了, (覺得用 strong 修飾也可以但是沒有必要) 新增到子控制元件也是強引用: UIbutton 就是新增到了 UIviewController 的 view 上

8 預處 指令define 宣告 個常數, 以表明 中有多 少秒(忽 閏 問題)。

define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL

9.重寫-個NSString型別的,retain 式宣告name屬性的 setter和getter 法(MRC)

屬性的三大特性:語義特性,原子特性,讀寫特性. 同時重寫setter和getter方法,@synchronized name = _name,關聯屬性和例項變數 如 -(void)setName:(NSString *)name{ if(_name != name){ [_name retain]; [_name release]; _name = name; } } -(NSString *)name{ return [[_name retain]autorelease] }

10.分析json、xml 的區別? json、xml 解析 式的底層是如何讓處理的

(一)JSON與XML的區別: (1)可讀性方面:基本相同,XML的可讀性比較好; (2)可擴充套件性方面:都具有良好的擴充套件性; (3)編碼難度方面:相對而言,JSON的編碼比較容易; (4)解碼難度:JSON的解碼難度基本為零,XML需要考慮子節點和父節點; (5)資料體積方面:JSON相對於XML來講,資料體積小,傳遞的速度比較快; (6)資料互動方面:JSON與javascript的互動更加方便,更容易解析處理,更好的資料互動; (7)資料描述方面:XML對資料描述性比較好 (8)傳輸速度方面:JSON的速度遠遠快於XML。 (二)JSON與XML底層實現原理:  (1)JSON底層原理:遍歷字串中的字元,最終根據格式規定的特殊字元,比如{}、[]、:等進行區分,{}號表示字典,[]號表示陣列,:號是字典的鍵和值的分水嶺,最終仍是將JSON轉化為字典,只不過字典中的值可能是“字典、陣列或者字串而已”。   (2)XML底層原理:XML解析常用的解析方法有兩種:DOM解析和SAX解析;DOM採用的是樹形結構的方式訪問XML文件,而SAX採用的是事件模型;DOM解析把XML文件轉化為一個包含其內容的樹,並可以對樹進行遍歷,使用DOM解析器的時候需要處理整個XML文件,所以對記憶體和效能的要求比較高;SAX在解析XML文件的時候可以觸發一系列的事件,當發現給定的tag的時候,他可以啟用一個回撥方法,告訴該方法指定的標籤已經找到,SAX對記憶體的要求通常會比較低,因為他讓開發人員自己來決定所要處理的tag,特別是當開發人員只需要處理文件中所包含部分資料時,SAX這種擴充套件能力得到了更好的體現。

11.對程式效能的優化你有什麼建議?

1.使用複用機制 2.儘可能設定 View 為不透明 3.避免臃腫的 XIB 檔案 4.不要阻塞主執行緒 5.圖片尺寸匹配 UIImageView 6.選擇合適的容器 7.啟用 GZIP 資料壓縮 8.View 的複用和懶載入機制 9、快取 伺服器的響應資訊(response)。 圖片。 計算值。比如:UITableView 的 row heights。 10.關於圖形繪製 11.處理 Memory Warnings
在 AppDelegate 中實現 - [AppDelegate applicationDidReceiveMemoryWarning:] 代理方法。 在 UIViewController 中過載 didReceiveMemoryWarning 方法。 監聽 UIApplicationDidReceiveMemoryWarningNotification 通知。 12.複用高開銷的物件 13.減少離屏渲染(設定圓角和陰影的時候可以選用繪製的方法) 14.優化 UITableView 通過正確的設定 reuseIdentifier 來重用 Cell。 儘量減少不必要的透明 View。 儘量避免漸變效果、圖片拉伸和離屏渲染。 當不同的行的高度不一樣時,儘量快取它們的高度值。 如果 Cell 展示的內容來自網路,確保用非同步載入的方式來獲取資料,並且快取伺服器的 response。 使用 shadowPath 來設定陰影效果。 儘量減少 subview 的數量,對於 subview 較多並且樣式多變的 Cell,可以考慮用非同步繪製或重寫 drawRect。 儘量優化 - [UITableView tableView:cellForRowAtIndexPath:] 方法中的處理邏輯,如果確實要做一些處理,可以考慮做一次,快取結果。 選擇合適的資料結構來承載資料,不同的資料結構對不同操作的開銷是存在差異的。 對於 rowHeight、sectionFooterHeight、sectionHeaderHeight 儘量使用常量。 15.選擇合適的資料儲存方式 在 iOS 中可以用來進行資料持有化的方案包括: NSUserDefaults。只適合用來存小資料。 XML、JSON、Plist 等檔案。JSON 和 XML 檔案的差異在「選擇正確的資料格式」已經說過了。 使用 NSCoding 來存檔。NSCoding 同樣是對檔案進行讀寫,所以它也會面臨必須載入整個檔案才能繼續的問題。 使用 SQLite 資料庫。可以配合 FMDB 使用。資料的相對檔案來說還是好處很多的,比如可以按需取資料、不用暴力查詢等等。 使用 CoreData。也是資料庫技術,跟 SQLite 的效能差異比較小。但是 CoreData 是一個物件圖譜模型,顯得更物件導向;SQLite 就是常規的 DBMS。 16.減少應用啟動時間 快速啟動應用對於使用者來說可以留下很好的印象。尤其是第一次使用時。 保證應用快速啟動的指導原則: 儘量將啟動過程中的處理分拆成各個非同步處理流,比如:網路請求、資料庫訪問、資料解析等等。 避免臃腫的 XIB 檔案,因為它們會在你的主執行緒中進行載入。重申:Storyboard 沒這個問題,放心使用。 注意:在測試程式啟動效能的時候,最好用與 Xcode 斷開連線的裝置進行測試。因為 watchdog 在使用 Xcode 進行除錯的時候是不會啟動的。 17.使用 Autorelease Pool (記憶體釋放池) 18.imageNamed 和 imageWithContentsOfFile

12.runloop 和執行緒有什麼關係?

runloop與執行緒是一一對應的,一個runloop對應一個核心的執行緒,為什麼說是核心的,是因為runloop是可以巢狀的,但是核心的只能有一個,他們的關係儲存在一個全域性的字典裡。 runloop是來管理執行緒的,當執行緒的runloop被開啟後,執行緒會在執行完任務後進入休眠狀態,有了任務就會被喚醒去執行任務。 runloop在第一次獲取時被建立,線上程結束時被銷燬。 對於主執行緒來說,runloop在程式一啟動就預設建立好了。 對於子執行緒來說,runloop是懶載入的,只有當我們使用的時候才會建立,所以在子執行緒用定時器要注意:確保子執行緒的runloop被建立,不然定時器不會回撥。

13 介紹下layoutSubview和drawRect

layoutSubviews呼叫情況 init初始化UIView不會觸發呼叫 addSubview會觸發呼叫 改變view的width和height的時候回觸發呼叫 一個UIScrollView滾動會觸發呼叫 旋轉screen會觸發呼叫 改變一個UIView大小的時候會觸發superView的layoutSubviews事件 直接呼叫setLayoutSubviews會觸發呼叫 -(void)viewWillAppear:(BOOL)animated會觸發一次呼叫 -(void)viewDidAppear:(BOOL)animated 看情況,可能有呼叫 drawRect呼叫情況 如果UIView沒有設定frame大小,直接導致drawRect不能被自動呼叫。 drawRect在loadView和viewDidLoad這兩個方法之後呼叫 呼叫sizeToFit後自動呼叫drawRect 通過設定contentMode值為UIViewContentModeRedraw。那麼每次設定或者更改frame自動呼叫drawRect。 直接呼叫setNeedsDisplay或者setNeedsDisplayInRect會觸發呼叫

14.寫個“標準“巨集MIN,這個巨集輸兩個引數並返回較小的那個

MIN(A,B) ((A) <= (B) ? (A) : (B))

15.類別有什麼作用

1.擴充套件已有的類(新增方法) 2.可以通過runtime新增屬性

  1. 什麼是method swizzing?講 講你的使 場景以及使 時的注意事項

1.給擴充套件新增屬性 2.替換系統方法的的實現

22.講講iOS事件響應鏈的原理

1、響應者鏈通常是由檢視(UIView)構成的; 2、一個檢視的下一個響應者是它檢視控制器(UIViewController)(如果有的話),然後再轉給它的父檢視(Super View); 3、檢視控制器(如果有的話)的下一個響應者為其管理的檢視的父檢視; 4、單例的視窗(UIWindow)的內容檢視將指向視窗本身作為它的下一個響應者 需要指出的是,Cocoa Touch應用不像Cocoa應用,它只有一個UIWindow物件,因此整個響應者鏈要簡單一點; 5、單例的應用(UIApplication)是一個響應者鏈的終點,它的下一個響應者指向nil,以結束整個迴圈。

23.你在什麼場景下會選擇使 Category

1.擴充套件已有的類(新增方法)

24.UIview 和CAlayer 是什麼關係? 你 CLayer做過什麼?

  1. 首先UIView可以響應事件,Layer不可以.
  2. UIView是CALayer的delegate 3. UIView主要處理事件,CALayer負責繪製就更好 4. 每個 UIView 內部都有一個 CALayer 在背後提供內容的繪製和顯示,並且 UIView 的尺寸樣式都由內部的 Layer 所提供。兩者都有樹狀層級結構,layer 內部有 SubLayers,View 內部有 SubViews.但是 Layer 比 View 多了個AnchorPoint 建立隱式動畫 繪製邊框圓角

25.如何處理UITableVier 中Cell 動態計算高度的問題,都有哪些方案?

1、你的Cell要使用AutoLayout來佈局約束這是必須的; 設定tableview的estimatedRowHeight為一個非零值,這個屬性是設定一個預估的高度值,不用太精確。 設定tableview的rowHeight屬性為UITableViewAutomaticDimension 2.第三方 UITableView+FDTemplateLayoutCell

26.AutoLayout 中的優先順序是什麼? UIScrollView 中使用Autolayout 會出現什麼問題?

程式碼計算frame -> autoreszing(父控制元件和子控制元件的關係) -> autolayout(任何控制元件都可以產生關係) -> sizeclass 可以設定兩個看似有衝突的約束,但設定不同的優先順序之後就不會有衝突了,當其中一個約束失效之後,另一個優先順序比較低的約束就會起作用

27.NSIRLConnection 和NSLRLSession 的區別是 麼? NSURLProtocol是做什麼的?

1.下載 NSURLConnection下載檔案時,先是將整個檔案下載到記憶體,然後再寫入到沙盒,如果檔案比較大,就會出現記憶體暴漲的情況。 而使用NSURLSessionUploadTask下載檔案,會預設下載到沙盒中的tem檔案中,不會出現記憶體暴漲的情況,但是在下載完成後會把tem中的臨時檔案刪除,需要在初始化任務方法時,在completionHandler回撥中增加儲存檔案的程式碼 2.請求方法的控制 NSURLConnection例項化物件,例項化開始,預設請求就傳送(同步傳送),不需要呼叫start方法。而cancel可以停止請求的傳送,停止後不能繼續訪問,需要建立新的請求。 NSURLSession有三個控制方法,取消(cancel)、暫停(suspend)、繼續(resume),暫停以後可以通過繼續恢復當前的請求任務。 使用NSURLSession進行斷點下載更加便捷. NSURLSession的構造方法(sessionWithConfiguration:delegate:delegateQueue)中有一個NSURLSessionConfiguration類的引數可以設定配置資訊,其決定了cookie,安全和快取記憶體策略,最大主機連線數,資源管理,網路超時等配置。NSURLConnection不能進行這個配置,相比較與NSURLConnection依賴與一個全域性的配置物件,缺乏靈活性而言,NSURLSession有很大的改進

28.怎麼高效的實現控制元件的圓角效果

繪製圓角 -(UIImageView *)roundedRectImageViewWithCornerRadius:(CGFloat)cornerRadius { UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:cornerRadius]; CAShapeLayer *layer = [CAShapeLayer layer]; layer.path = bezierPath.CGPath; self.layer.mask = layer; return self; }

32.說說你瞭解weak屬性?

weak關鍵字在OC中屬於比較基礎的知識此特性表明該屬性定義了一種關係“非擁有關係”(nonowning relationship)。為這種屬性設定新值得時,設定方法既不保留新值,也不釋放舊值。此特性同assign類似,然後在屬性所指的物件遭到摧毀時,屬性值也會清空(nil out)。 弱引用,不決定物件的存亡。即使一個物件被持有無數個弱引用,只要沒有強引用指向它,那麼還是會被清除。

33.假如Controller太臃腫,如何優化?

1.將網路請求抽象到單獨的類中 方便在基類中處理公共邏輯; 方便在基類中處理快取邏輯,以及其它一些公共邏輯; 方便做物件的持久化。 2.將介面的封裝抽象到專門的類中 構造專門的 UIView 的子類,來負責這些控制元件的拼裝。這是最徹底和優雅的方式,不過稍微麻煩一些的是,你需要把這些控制元件的事件回撥先接管,再都一一暴露回 Controller。 3.構造 ViewModel 借鑑MVVM。具體做法就是將 ViewController 給 View 傳遞資料這個過程,抽象成構造 ViewModel 的過程。 4.專門構造儲存類 專門來處理本地資料的存取。 5.整合常量

34.專案中網路層如何做安全處理?

1.判斷API的呼叫請求是否來自於經過授權的APP。如若不是則拒絕請求訪問 2.在資料請求的過程中進行URL加密處理:防止反編譯,介面資訊被靜態分析。 3.資料傳輸加密:對客戶端傳輸資料提供有效的加密方案,以防止網路介面的攔截。 如果可以儘量使用HTTPS,可以有效的避免介面資料在傳輸中被攻擊。

35.main()之前的過程有哪些?

在iOS中 main.m 是我們所熟悉的程式入口。但是在在此之前其實程式以及做了很多事了。如系統會獲取dyld的路徑,並載入。載入程式中的依賴庫。呼叫所有的+ load方法,並返回main函式地址。

其他值得看的總結:

見過的最全的iOS面試題 iOS最新面試題彙總 招聘一個靠譜的 iOS

BAT面試題

出自:不懂技術的愛迪生

騰訊一面 1.使用了第三方庫, 有看它們是怎麼實現的嗎? 2.強連通量演算法瞭解嘛? 3.遇到tableView卡頓嘛?會造成卡頓的原因大致有哪些? 4.M、V、C相互通訊規則你知道的有哪些? 5.NStimer準嗎?談談你的看法?如果不準該怎樣實現一個精確的NSTimer? 答案詳見:https://www.jianshu.com/p/0e9e7486e1a7

騰訊二面: 1.編譯過程做了哪些事情; 2.字典大致實現原理; 3.block和函式指標的理解; 4.一般開始做一個專案,你的架構是如何思考的? 5.你瞭解的UIKit結構? 答案詳見:https://www.jianshu.com/p/dd17bdcff9f7

騰訊三面 1.OC你瞭解的鎖有哪些?在你回答基礎上進行二次提問; 追問一:自旋和互斥對比? 追問二:用C/OC/C++,任選其一,實現自旋或互斥?口述即可! 2.記憶體洩漏可能會出現的幾種原因,聊聊你的看法? 追問一:非OC物件如何處理? 追問二:若常用框架出現記憶體洩漏如何處理? 3.容錯處理你們一般是怎麼做的? 4.專案開始容錯處理沒做?如何防止攔截潛在的崩潰? 答案詳見:https://www.jianshu.com/p/3a50d1805655

阿里 1.dSYM你是如何分析的? 2.多執行緒有哪幾種?你更傾向於哪一種? 3.單例弊端? 4.如何把非同步執行緒轉換成同步任務進行單元測試? 5.介紹下App啟動的完成過程? 6.比如App啟動過慢,你可能想到的因素有哪些? 7.0x8badf00d表示是什麼? 8.怎麼防止反編譯? 9.說說你遇到到的技術難點? 10.說說你瞭解的第三方原理或底層知識? 答案詳見:http://url.cn/5oWSdgZ

其他更多BAT面試題可以連結: https://pan.baidu.com/s/1zTjFig0R4MdtBJdZIdfJug 密碼: rbta 下載

相關文章