現在已經不斷有網友發我他們在面試中遇到的面試題,這是一位程序媛前面在面試中遇到的問題
前面兩個過于基礎,從提高題開始分享;個人見解,勿噴
持續關注:iOS開發_小賢,持續輸出各大公司iOS面試系列文章,歡迎廣大程序猿找我投稿面試中碰到的面試題,我會給你一份我的見解和答案,順便給大家推薦一個iOS進階學習群:763164022!群內會有幾百道最新的面試題以及答案分享!歡迎大家入駐
題一:what is purpose ofdelegates?
代理的?的是改變或傳遞控制鏈。允許?個類在某些特定時刻通知到其他類,而不需要獲取到那些類的指針。可以減少框架復雜度。
什么是代理?
代理是?種通?的設計模式,代理主要由三部分組成
?、協議:用來指定代理雙方可以做什么,必須做什么;
二、代理:根據指定的協議,完成委托?需要實現的功能;
三、委托:根據指定的協議,指定代理去完成什么功能。
代理的實現流程
在iOS中代理的本質就是代理對象內存的傳遞和操作,我們在委托類設置代理對象后,實際上只是?一個id類型的指針將代理對象進?了一個弱引?。委托?讓代理方執?操作,實際上是在委托類中向這個id類型指針指向的對象發送消息,?這個id類型指針指向的對象,就是代理對象。
代理的內存管理
使?代理如果聲明的不對,會造成循環引?的問題。?般會?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