iOS面試現場,筆試提升題詳解

如今已經不斷有網友發我他們在面試中遇到的面試題,這是一位程序媛前面在面試中遇到的問題面試

面試題

前面兩個過於基礎,從提升題開始分享;我的看法,勿噴設計模式

持續關注:logic_楚陽,持續輸出各大公司iOS面試系列文章,歡迎廣大程序猿找我投稿面試中碰到的面試題,我會給你一份個人看法和答案,前面已經分享100道我招聘的面試題,加入下方iOS技術交流羣624212887直接獲取

題一:what is purpose ofdelegates?

代理的⽬的是改變或傳遞控制鏈。容許⼀個類在某些特定時刻通知到其餘類,而不須要獲取到那些類的指針。能夠減小框架複雜度。數組

什麼是代理?緩存

代理是⼀種通⽤的設計模式,代理主要由三部分組成服務器

⼀、協議:用來指定代理雙方能夠作什麼,必須作什麼;app

2、代理:根據指定的協議,完成委託⽅須要實現的功能;框架

3、委託:根據指定的協議,指定代理去完成什麼功能。函數

代理的實現流程性能

在iOS中代理的本質就是代理對象內存的傳遞和操做,咱們在委託類設置代理對象後,實際上只是⽤一個id類型的指針將代理對象進⾏了一個弱引⽤。委託⽅讓代理方執⾏操做,其實是在委託類中向這個id類型指針指向的對象發送消息,⽽這個id類型指針指向的對象,就是代理對象。ui

代理的內存管理

使⽤代理若是聲明的不對,會形成循環引⽤的問題。⼀般會⽤weak修飾,⽤strong修飾會形成循環引⽤問題,⽤assign修飾會形成crash。

代理與其餘iOS中消息傳遞的⽅式的對⽐

通知:在iOS中由通知中⼼進⾏消息接收和消息⼴播,是⼀種⼀對多的消息傳遞⽅式。

代理:是⼀種通⽤的設計模式,iOS中對代理⽀持的很好,由代理對象、委託者、協議三部分組成。

Block:iOS4.0中引⼊的⼀種回調⽅法,能夠將回調處理代碼直接寫在block代碼塊中,看起來邏輯清晰代碼整⻬。

target action:經過將對象傳遞到另⼀個類中,在另⼀個類中將該對象當作target的⽅式,來調⽤該對象⽅法,從內存⻆度來講和代理相似。

KVO:NSObject的Category-NSKeyValueObserving,經過屬性監聽的⽅式來監測某個值的變化,當值發⽣變化時調⽤KVO的回調⽅法。

代理與block的對⽐

  1. 多個消息傳遞,應該使⽤delegate。在有多個消息傳遞時,⽤delegate實現更合適,看起來也更清晰。block就不太好了,這個時候block反而不便於維護,⽽且看起來⾮常臃腫,很彆扭。例如UIKit的UITableView中有不少代理若是都換成block實現,會⽐比delegates難⽤好多。

2.一個委託對象的代理屬性只能有⼀個代理對象,若是想要委託對象調⽤多個代理對象的回調應該用block。

3.單例對象最好不要⽤delegate。單例對象因爲始終都只是同⼀個對象,若是使⽤delegate,就會形成delegate屬性被從新賦值的問題,最終只能有一個對象能夠正常響應代理⽅法。

4.代理更加⾯相過程,block則更面向結果。從設計模式的角度來講,代理更加面向過程,⽽block更加⾯向結果。

5.從性能上來講,block的性能消耗要略大於delegate,由於block會涉及到棧區向堆區拷⻉等操做,時間和空間上的消耗都⼤於代理。⽽代理只是定義了⼀個⽅法列表,在遵照協議對象的objc_protocol_list中添加⼀個節點,在運⾏時向遵照協議的對象發送消息便可

題二:Objective C中多重繼承的實現機制。

什麼是多繼承?

假設C類要同時繼承A類和B類,則稱之爲多繼承。這種狀況就是多繼承。

oc中的「多繼承」

其實Objective-C不支持多繼承,因爲消息機制名字查找發⽣在運⾏時⽽非編譯時,很難解決多個基類可能致使的⼆義性問題。不過其實Objective-C 也⽆需⽀持多繼承,咱們能夠找到以下⼏種間接實現多繼承⽬的方法:

  1. 經過組合實現「多繼承」

  2. 經過協議實現「多繼承」

經過組合實現「多繼承」

圖片描述

經過協議實現「多繼承」

雖然OC在語法上禁⽌類使⽤多繼承,可是卻能夠⽤協議來實現多繼承。協議只能提供接⼝,而沒有提供實現⽅式,若是隻是想多繼承基類的接⼝,那麼遵照多協議⽆疑是最好的⽅法。

此⽅法缺點⽐較明顯:須要修改兩個⽗類,同時並不能調⽤兩個⽗類的原⽣⽅法,須要在⼦類中實現⽅法。

圖片描述

題三:簡述Singleton的概念及並使用Objective C 寫出相關代碼。

Singleton: 單例模式。 簡單來講, 就是保證在你不主動銷燬這個單例對象的狀況下, 整個項目中都始終擁有這

個單例對象, 而且這個單例對象在內存中都是同一個內存地址。

因此, 單例很重要的兩個特色:

(1) app生命週期中一直存在(除主動銷燬外)

(2) 在整個生命週期中, 都是同一個內存地址

根據這兩個特色, 我來描述一個應用中的使用場景。 最簡單和經常使用的就是, 咱們用戶的登陸信息, 不作本地緩存的話, 咱們登陸成功以後, 把服務器請求下來的用戶信息保存到單例中。 好比這樣 [UserSingletonshareInstance].name = 「張山」。 接下來, 你不管在應用的任何頁面均可以直接經過[UserSingleton shareInstance].name的方式獲取到用戶的名字, 並且這個名字都是」張三」。 其餘作法,都會比這個麻煩。

那麼怎麼寫單例呢? 核心的一點就是, 咱們平時建立一個實例對象時候用到的方法(alloc, init), 都要重寫一遍,保證使用這些方法建立對象的時候是隻分配一塊內存地址,而後第一次建立以後再建立都指向前邊已經建立過得那個內存地址,順着這個思路,代碼以下:

#import "Singleton.h" @interface Singleton()<NSCopying,NSMutableCopying> @end @implementation Singleton static Singleton* _instance = nil; +(instancetype) shareInstance {     static dispatch_once_t onceToken ;     dispatch_once(&onceToken, ^{         _instance = [[super allocWithZone:NULL] init] ;         //不是使用alloc方法,而是調用[[super allocWithZone:NULL] init]         //已經重載allocWithZone基本的對象分配方法,因此要借用父類(NSObject)的功能來幫助出處理底層內存分配的雜物     }) ;  return _instance ; } +(id) allocWithZone:(struct _NSZone *)zone {     return [Singleton shareInstance] ; } -(id) copyWithZone:(NSZone *)zone {     return [Singleton shareInstance] ;//return _instance; } -(id) mutablecopyWithZone:(NSZone *)zone {     return [Singleton shareInstance] ; } @end

而後,OC有個語法糖能夠寫:

#import "Manager.h" @implementation Manager +(Manager *)sharedManager{     static dispatch_once_t predicate;     static Manager * sharedManager;     dispatch_once(&predicate, ^{         sharedManager=[[Manager alloc] init];     });     return sharedManager; } @end

題四:簡述@selector的做用

Selector/SEL又叫方法選擇器,SEL在objc.h中是這樣聲明的,而「@selector()」是取得一個SEL指針。說白了,方法選擇器僅僅是一個char *指針,表示它所表明的是方法的名字。 簡單來講: 「@Selector 就是用字符串表示某個類的某個方法。」 更加專業的說法是: 「Selector就是OC的虛擬表(virtual table)中指向實際執行的函數指針(function pointer)的一個C字符。」

咱們通常用它來「由於method能夠用字符串表示,所以,某個method就能夠變成用來傳遞的參數。」 再說的透明一點, 由於 selector 能夠看作是函數的另外一個名字,因此不少須要調用函數或者創建鏈接的地方,均可以用到,如下是一些具體的使用場景:

  • Target/Action 模式

  • 檢查 method 是否存在

  • Timer

  • 在線程中執行方法

  • 數組排序

  • 代替 if else / switch

  • 調用私有 API

相關文章
相關標籤/搜索