一個知乎iOS面試題答案

本文將回答知乎上iOS面試問題鏈接:如何面試 iOS 工程師?

Model層:

數(shù)據(jù)持久化存儲方案有哪些?沙盒的目錄結構是怎樣的?各自一般用于什么場合?SQL語句問題:inner join、left join、right join的區(qū)別是什么?sqlite的優(yōu)化網(wǎng)絡通信用過哪些方式(100%的人說了AFNetworking...)如何處理多個網(wǎng)絡請求并發(fā)的情況
在網(wǎng)絡請求中如何提高性能
在網(wǎng)絡請求中如何保證安全性

語言與基礎知識:

內(nèi)存中的棧和堆的區(qū)別是什么?那些數(shù)據(jù)在棧上,哪些在堆上?#define和const定義的變量,有什么區(qū)別什么情況下會出現(xiàn)內(nèi)存的循環(huán)引用block中的weak self,是任何時候都需要加的么?GCD的queue,main queue中執(zhí)行的代碼,一定是在main thread么?
NSOperationQueue有哪些使用方式
NSThread中的Runloop的作用,如何使用?
.h文件中的變量,外部可以直接訪問么?(注意是變量,不是property)講述一下runtime的概念,message send如果尋找不到相應的對象,會如何進行后續(xù)處理 ?TCP和UDP的區(qū)別是什么?
MD5和Base64的區(qū)別是什么,各自場景是什么?
二叉搜索樹的概念,時間復雜度多少?

架構:(我們招的不是架構師,這方面問的不多,而且從之前對APP的架構介紹里可以邊聽邊問)

哪些類不適合使用單例模式?即使他們在周期中只會出現(xiàn)一次。
Notification的使用場景是什么?同步還是異步?
簡單介紹一下KVC和KVO,他們都可以應用在哪些場景?

APP相關:

如何添加一個自定義字體到工程中
如何制作一個靜態(tài)庫/動態(tài)庫,他們的區(qū)別是什么?
Configuration中,debug和release的區(qū)別是什么?
簡單介紹下發(fā)送系統(tǒng)消息的機制(APNS) UI:
系統(tǒng)如何尋找到需要響應用戶操作的那個Responder
多屏幕尺寸的適配
UIButton的父類是什么?UILabel呢?
push view controller 和 present view controller的區(qū)別
描述下tableview cell的重用機制
UIView的frame和bounds的區(qū)別是什么

最后是幾道場景題,也是我最喜歡問的:

發(fā)送10個網(wǎng)絡請求,然后再接收到所有回應之后執(zhí)行后續(xù)操作,如何實現(xiàn)?
實現(xiàn)一個第三方控件,可以在任何時候出現(xiàn)在APP界面最上層
實現(xiàn)一個最簡單的點擊拖拽功能。上面那個拖拽之外,如果在手放開時,需要根據(jù)速度往前滑動呢?
如何減小一個應用程序的尺寸?
如何提高一個性用程序的性能?
不同版本的APP,數(shù)據(jù)庫結構變化了,如何處理?

作者:張之誠
鏈接:https://www.zhihu.com/question/19604641/answer/56306604
來源:知乎

下面是給出的答案,有不對的地方還請多多指教!

一. 數(shù)據(jù)持久化存儲方案有哪些?

  1. 屬性列表(NSUserdefaults)
    NSUserdefaults適合存儲輕量級,弱業(yè)務相關的數(shù)據(jù),存儲在應用程序的一個plist文件里,Document目錄平級的/Library/Prefereces里。
  2. NSCoding
  3. 文件存儲(NSFileManager)
  4. NSKeydeArchive歸檔存儲
    又名序列化,把對象轉(zhuǎn)為字節(jié)碼,通過key-value以文件的形式加密存儲在磁盤上
  5. 數(shù)據(jù)庫
    SQlite庫提供了三種方式:Single Thread, Multi Thread, Serialized(默認)
    Serialized串行隊列執(zhí)行所有操作,
  6. Keychain
    蘋果提供的帶有可逆加密的存儲機制,存儲密碼和用戶唯一標識串。

二. 沙盒的目錄結構是怎樣的?各自一般用于什么場合?

在應用的安裝過程中,系統(tǒng)為每個單獨的應用程序生成它的主目錄和一些關鍵的子目錄。蘋果對沙盒的幾天限制:

  1. 應用程序在自己的沙盒中運作,不能訪問任何其他應用程序的沙盒;
  2. 應用之間不能共享數(shù)據(jù);
  3. 蘋果禁止任何讀寫沙盒以外的文件,禁止應用程序?qū)?nèi)容寫到沙盒以外的文件中;
  4. 沙盒目錄里有三個文件夾:Documents、Library、Temp、AppName.app目錄
    Documents-----存儲;應用程序的數(shù)據(jù)文件,存儲用戶數(shù)據(jù)或其他定期備份的信息;
    library下有兩個文件夾:Caches存儲應用程序再次啟動所需的信息,
    Preferences包含應用程序的偏好設置文件,不可在這更改偏好設置;
    temp存儲臨時文件
  5. 獲取沙盒根目錄方法:NSHomeDirectory獲取
    獲取Document路徑
    NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).

三. SQL語句問題:inner join、left join、right join的區(qū)別是什么?

left join(左聯(lián)接)返回包括左表中的所有記錄和右表中聯(lián)結字段相等的記錄
right join(右聯(lián)接)返回包含右表中的所有記錄和左表中聯(lián)接字段相等的記錄
inner join (等值聯(lián)接) 只返回兩個表中聯(lián)接字段相等的行
select *from A left join B on A.id = B.id

四. 在網(wǎng)絡請求中如何提高性能?

1.減少請求寬帶:(壓縮請求與響應)
(1)使用JSON數(shù)據(jù),高效的數(shù)據(jù)交換格式
(2)Base64格式上傳文件,對Base64數(shù)據(jù)進行壓縮,減少30%的數(shù)據(jù)體積
2.降低請求延遲:(管道化請求)
(1)降低多個請求的延遲
(2)在單個TCP連接上發(fā)送HTTP請求,以管道的形式發(fā)送HTTP請求,從而優(yōu)化全雙工TCP連接的使用。
(3)Apache和IIS都支持管道,無需任何額外的配置。
3.避免網(wǎng)絡請求
(1)在本地緩存內(nèi)容避免不必要的網(wǎng)絡流量

五. 在網(wǎng)絡請求中如何保證安全性

https 和 加密

六. 內(nèi)存中的棧和堆的區(qū)別是什么?那些數(shù)據(jù)在棧上,哪些在堆上?

棧區(qū)是由編譯器自動分配釋放,存放方法(函數(shù))的參數(shù)值,局部變量的值等,棧是向低地址擴展的數(shù)據(jù)結構,是一塊連續(xù)的內(nèi)存區(qū)域。棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預先規(guī)定好的。
堆由程序員分配釋放,若不釋放,程序結束時由OS回收,向高地址擴展的數(shù)據(jù)結構,是不連續(xù)的內(nèi)存區(qū)域,
OC對象放在堆內(nèi),非OC對象一般放在棧里面
棧是吃了吐,堆是吃了拉
鏈接:iOS 堆和棧的區(qū)別?

七. #define和const定義的變量,有什么區(qū)別:

1.#define在預處理階段進行簡單的替換,const在編譯階段使用;
2.#define不做類型檢查,只是簡單的替換,const有數(shù)據(jù)類型會執(zhí)
行類型檢查;
3.#define不能調(diào)試, const可以調(diào)試
4.#define大量的宏造成編譯時間久
5.#define可以定義一些簡單的函數(shù),const不可以
6.const修飾右邊的變量只讀 NSString * const p

static作用:

  1. 修飾局部變量
    (1)延長局部變量的生命周期,程序結束才會銷毀
    (2)局部變量只會生成一份內(nèi)存,只會初始化一次
  2. 修飾全局變量:只能在本文件中訪問,修改全局變量的作用域,生命周期不會改

extern作用:聲明全局變量
聲明一個變量,不能定義變量

static和const聯(lián)合使用:聲明一個靜態(tài)全局只讀變量
static NSString * const name = @"name";

extern與const聯(lián)合使用
當有多個文件使用同一個字符串常量時,可以使用extern和const組合

新建一個全局的文件管理全局的變量
在.m里定義 NSString *const YYTextViedBegin = @"YYTextVditing";
在.h里應用 UIKIT_EXTERN NSString *const YYTextViewTextDidBegin;

八. 什么情況下會出現(xiàn)內(nèi)存的循環(huán)引用

block,A強引用了block,block有強引用了A

九. block中的weak self,是任何時候都需要加的么?

只有產(chǎn)生循環(huán)引用了才會加

十. GCD的queue,main queue中執(zhí)行的代碼,一定是在main thread么?

對于queue中所執(zhí)行的代碼不一定在main thread中。如果
queue是在主線程中創(chuàng)建的,那么所執(zhí)行的代碼就是在主線程中執(zhí)行。如果是在子線程中創(chuàng)建的,那么就不會在main thread中執(zhí)行。
對于main queue就是在主線程中的,因此一定會在主線程中執(zhí)行。獲取 main queue就可以了,不需要我們創(chuàng)建,獲取方式通過調(diào)用方法 dispatchgetmain_queue來獲取。
鏈接:多線程

十一. NSOperationQueue有哪些使用方式

鏈接:iOS多線程之NSOperationQueue

與GCD的區(qū)別

  1. GCD使用方便,代碼邏輯清晰,
  2. GCD是C語言構成的API,NSOperationQueue是基于GCD的Objective-C對象的封裝,提供了更多的選擇
  3. NSOperationQueue任務可以很方便的取消未執(zhí)行的任務
  4. GCD只支持FIFO隊列,NSOperation可以通過依賴關系設置操作執(zhí)行順序,控制在特定的任務執(zhí)行完后才執(zhí)行,GCD可以通過barrier或者group控制執(zhí)行順序,但是依賴關系復雜時,代碼邏輯太復雜
  5. NSOperation支持KVO監(jiān)聽任務的狀態(tài)(完成、執(zhí)行中、取消等狀態(tài))
  6. NSOperation可以設置同一隊列中任務的優(yōu)先級,GCD只能區(qū)分不同隊列的優(yōu)先級
  7. 自定義NSOperation,封裝任務邏輯,提高整個代碼的復用度

十二. NSThread中的Runloop的作用,如何使用

runloop是一個線程里運行循環(huán),并對收到的事件進行處理,

  1. 保持線程長時間存活
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    [runLoop addPort:[NSMachPort port] forMode:NSRunLoopCommonModes];
    [runLoop run];
  2. 用于定時器

十三. .h文件中的變量,外部可以直接訪問么?(注意是變量,不是property)

成員變量三中權限:@private, @protected, @public
不可以,.h中的成員變量默認是@protected權限,子類可以訪問,可以做權限修改,外部調(diào)用會報protected錯誤

十四. 講述一下runtime的概念,message send如果尋找不到相應的對象,會如何進行后續(xù)處理 ?

objc向一個對象發(fā)送消息,runtime會根據(jù)對象的isa指針找到該對象實際所屬類,然后在該類方法列表以及父類的方法列表中查找方法實現(xiàn),如果向一個nil對象發(fā)送消息,在查找isa指針時就是0地址返回,不會出錯

十五. TCP和UDP的區(qū)別是什么?

TCP:面向連接、傳輸可靠(保證數(shù)據(jù)正確性,數(shù)據(jù)順序)、用于傳輸大量數(shù)據(jù)(流模式)、速度慢、建立連接需要開銷較多(時間,系統(tǒng)資源)。
UDP:面向非連接、傳輸不可靠、用于傳輸少量數(shù)據(jù)(數(shù)據(jù)包模式)、速度快。
TCP在連接持續(xù)過程中,socket收到的數(shù)據(jù)是同一臺主機發(fā)出。
UDP只要知道接收端的IP和端口,網(wǎng)絡可達,任何主機都可以向接受端發(fā)送數(shù)據(jù)

十六. MD5和Base64的區(qū)別是什么,各自場景是什么

MD5是用哈希算法(摘要算法)加密的:不可逆;密文總是16進制32位
一般用于文件校驗、密碼存儲
Base64是公開的代碼加密,url加密

十七. 二叉搜索樹的概念,時間復雜度多少

采用二叉樹鏈表作為存儲結構,每個左節(jié)點均小于父節(jié)點,每個右節(jié)點均大于父節(jié)點
時間復雜度:O(log2(n))

十八. 哪些類不適合使用單例模式?即使他們在周期中只會出現(xiàn)一次。

同一類型的對象需要在不同的用例場景發(fā)生變化

十九. Notification的使用場景是什么?同步還是異步?

一對多,同步

二十. 簡單介紹一下KVC和KVO,他們都可以應用在哪些場景?

KVO:鍵值監(jiān)聽,觀察某一屬性的方法
KVC:鍵值編碼,間接訪問對象的屬性

二十一. 如何添加一個自定義字體到工程中
> 添加ttf文件,通過[UIFont fontWithName:@“字體名” size:20]使用

二十二. 如何制作一個靜態(tài)庫/動態(tài)庫,他們的區(qū)別是什么?

靜態(tài)庫在編譯時期:commond+shift+N(即新建工程)----->FrameWork&library—>Cocoa Touch Static Libiary
動態(tài)庫在運行時期:commond+shift+N(即新建工程)----->FrameWork&library—>Cocoa Touch Libiary
區(qū)別:靜態(tài)庫:模塊化,分工合作,避免少量改動,但是會導致大量的重復編譯連接,也可以重用,注意不是共享使用 動態(tài)庫:可將可執(zhí)行的文件體積縮小,多個應用程序用同一份庫文件,節(jié)省資源

二十三. Configuration中,debug和release的區(qū)別是什么?

debug :測試時期,調(diào)試版本,能設置斷點,單步執(zhí)行 release:發(fā)行版本,體積小,運行速度快

二十四. 簡單介紹下發(fā)送系統(tǒng)消息的機制(APNs)

蘋果的APNS不保證送達率,如你網(wǎng)絡不好,在APNs那里下線,只保留最后一條消息,并告知推送數(shù),其他消息會被APNs丟棄。

UI:

二十五. 系統(tǒng)如何尋找到需要響應用戶操作的那個Responder

系統(tǒng)通過調(diào)用hitTest:withEvent:接受位置參數(shù)CGPoint,從底層按照subview的順序,測試該點在哪個view上,如果在該view上,則繼續(xù)測試是否在view的subview上。。。
響應鏈是從底層往上的,當沒有可以處理的responder時按響應鏈往上回溯,一直到application也無人處理則丟棄

二十六. 多屏幕尺寸的適配

Autolayout、Masonry、SDAutoLayout、純Frame計算比例

二十七. UIButton的父類是什么?UILabel呢?

UIControl UIView

二十八. push view controller 和 present view controller的區(qū)別

是否使用UINavigationController

二十九. 描述下tableview cell的重用機制

當cell被移出界面,進入重用池,當cell要顯示時候從重用池中獲取cell

三十. UIView的frame和bounds的區(qū)別是什么

Frame是參考父視圖的坐標系,bounds參考自身坐標系

三十一. 發(fā)送10個網(wǎng)絡請求,然后再接收到所有回應之后執(zhí)行后續(xù)操作,如何實現(xiàn)?

GCD信號量,隊列組

  1. 做法:通過dispatch_group_t來實現(xiàn),將每個請求放入到Group中,將合并成大圖的操作放在dispatch_group_notify中實現(xiàn)。
    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(), ^{
    // 合并圖片
    });
  2. dispatch_group_enter()和dispatch_group_leave()

三十二. 實現(xiàn)一個第三方控件,可以在任何時候出現(xiàn)在APP界面最上層

三十三. 實現(xiàn)一個最簡單的點擊拖拽功能。

三十四. 上面那個拖拽之外,如果在手放開時,需要根據(jù)速度往前滑動呢?

三十五. 如何減小一個應用程序的尺寸?
鏈接:減小iOS App或者靜態(tài)庫體積
鏈接: iOS App 瘦身 - 以 Swift App Yep 為例

三十六. 如何提高一個應用程序的性能?
鏈接:25條提高iOS App性能的建議和技巧

三十七. 不同版本的APP,數(shù)據(jù)庫結構變化了,如何處理?
數(shù)據(jù)庫遷移

  1. 運行APP后,判斷是否存在數(shù)據(jù)庫,不存在則直接創(chuàng)建數(shù)據(jù)庫,若存在取出數(shù)據(jù)庫版本號進行case處理
  2. 第一次運行APP,第一次建立版本庫,將數(shù)據(jù)信息存入數(shù)據(jù)庫,同時保存一個當前版本加一的字段到數(shù)據(jù)庫中
  3. 當APP更新時,從數(shù)據(jù)庫中取出數(shù)據(jù)庫中保存的版本字段,然后case執(zhí)行相關方法,修改完數(shù)據(jù)結構以后,再一次將版本字段加一存到數(shù)據(jù)庫中。
    鏈接:App升級時數(shù)據(jù)庫的遷移更新
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容

  • iOS面試小貼士 ———————————————回答好下面的足夠了------------------------...
    不言不愛閱讀 2,002評論 0 7
  • 多線程、特別是NSOperation 和 GCD 的內(nèi)部原理。運行時機制的原理和運用場景。SDWebImage的原...
    LZM輪回閱讀 2,027評論 0 12
  • 史上最全的iOS面試題及答案 iOS面試小貼士———————————————回答好下面的足夠了----------...
    Style_偉閱讀 2,410評論 0 35
  • ———————————————回答好下面的足夠了---------------------------------...
    恒愛DE問候閱讀 1,753評論 0 4
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,205評論 30 471