咱們接着上篇文章iOS面試基礎知識 (一)繼續給你們分享一下iOS面試題。html
OC不像C++等高級語言能直接繼承多個類,不過OC可使用類別和協議來實現多繼承。git
在App加載時,Runtime會把Category的實例方法、協議以及屬性添加到類上;把Category的類方法添加到類的metaclass上。github
1)在類別中不能直接以@property的方式定義屬性,OC不會主動給類別屬性生成setter和getter方法;須要經過objc_setAssociatedObject來實現。面試
@interface TestClass(ak) @property(nonatomic,copy) NSString *name; @end @implementation TestClass (ak) - (void)setName:(NSString *)name{ objc_setAssociatedObject(self, "name", name, OBJC_ASSOCIATION_COPY); } - (NSString*)name{ NSString *nameObject = objc_getAssociatedObject(self, "name"); return nameObject; }
2)類別同名方法覆蓋問題異步
關於類別更深刻的解析能夠參見美團的技術文章深刻理解Objective-C:Categoryide
iOS中的協議相似於Java、C++中的接口類,協議在OC中能夠用來實現多繼承和代理。oop
協議中的方法能夠聲明爲@required(要求實現,若是沒有實現,會發出警告,但編譯不報錯)或者@optional(不要求實現,不實現也不會有警告)。
筆者常常會問面試者以下兩個問題:
-怎麼判斷一個類是否實現了某個協議?不少人不知道能夠經過conformsToProtocol來判斷。
-假如你要求業務方實現一個delegate,你怎麼判斷業務方有沒有實現dalegate的某個方法?不少人不知道能夠經過respondsToSelector來判斷。post
iOS中的通知中心其實是觀察者模式的一種實現。ui
同步調用。當調用addObserver方法監聽通知,而後調用postNotification拋通知,postNotification會在當前線程遍歷全部的觀察者,而後依次調用觀察者的監聽方法,調用完成後纔會去執行postNotification後面的代碼。atom
經過addObserverForName:object:queue:usingBlock來實現異步通知。
1)調用setValue:forKey時候,好比[obj setValue:@"akon" forKey:@"key"]時候,會按照_key,_iskey,key,iskey的順序搜索成員並進行賦值操做。若是都沒找到,系統會調用該對象的setValue:forUndefinedKey方法,該方法默認是拋出異常。
2)當調用valueForKey:@"key"的代碼時,KVC對key的搜索方式不一樣於setValue"akon" forKey:@"key",其搜索方式以下:
咱們常常會使用KVC來設置屬性和獲取屬性,可是若是對象沒有按照KVC的規則聲明該屬性,則會形成crash,怎麼全局通用地防止這類崩潰呢?
能夠經過寫一個NSObject分類來防崩潰。
@interface NSObject(AKPreventKVCCrash) @end @ implementation NSObject(AKPreventKVCCrash) - (void)setValue:(id)value forUndefinedKey:(NSString *)key{ } - (id)valueForUndefinedKey:(NSString *)key{ return nil; } @end
KVO(Key-Value Observing),鍵值觀察。它是一種觀察者模式的衍生。其基本思想是,對目標對象的某屬性添加觀察,當該屬性發生變化時,經過觸發觀察者對象實現的KVO接口方法,來自動的通知觀察者。
經過以下兩個方案來註冊、移除KVO
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context; - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
經過observeValueForKeyPath來獲取值的變化。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
咱們能夠經過facebook開源庫KVOController方便地進行KVO。
蘋果官方文檔對KVO實現介紹以下:
Key-Value Observing Implementation Details
Automatic key-value observing is implemented using a technique called isa-swizzling.
The isa pointer, as the name suggests, points to the object's class which maintains a dispatch table. This dispatch table essentially contains pointers to the methods the class implements, among other data.
When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class. As a result the value of the isa pointer does not necessarily reflect the actual class of the instance.
You should never rely on the isa pointer to determine class membership. Instead, you should use the class method to determine the class of an object instance.
即當一個類型爲 ObjectA 的對象,被添加了觀察後,系統會生成一個派生類 NSKVONotifying_ObjectA 類,並將對象的isa指針指向新的類,也就是說這個對象的類型發生了變化。所以在向ObjectA對象發送消息時候,其實是發送到了派生類對象的方法。因爲編譯器對派生類的方法進行了 override,並添加了通知代碼,所以會向註冊的對象發送通知。注意派生類只重寫註冊了觀察者的屬性方法。
關於kvc和kvo更深刻的詳解參考iOS KVC和KVO詳解
在 ARC 下,咱們不須要手動管理內存,能夠徹底不知道 autorelease 的存在,就能夠正確管理好內存,由於 Runloop 在每一個 Runloop Circle 中會自動建立和釋放Autorelease Pool。
當咱們須要建立和銷燬大量的對象時,使用手動建立的 autoreleasepool 能夠有效的避免內存峯值的出現。由於若是不手動建立的話,外層系統建立的 pool 會在整個 Runloop Circle 結束以後才進行 drain,手動建立的話,會在 block 結束以後就進行 drain 操做,好比下面例子:
for (int i = 0; i < 100000; i++) { @autoreleasepool { NSString* string = @"akon"; NSArray* array = [string componentsSeparatedByString:string]; } }
好比SDWebImage中這段代碼,因爲encodedDataWithImage會把image解碼成data,可能形成內存暴漲,因此加autoreleasepool避免內存暴漲
@autoreleasepool { NSData *data = imageData; if (!data && image) { // If we do not have any data to detect image format, check whether it contains alpha channel to use PNG or JPEG format SDImageFormat format; if ([SDImageCoderHelper CGImageContainsAlpha:image.CGImage]) { format = SDImageFormatPNG; } else { format = SDImageFormatJPEG; } data = [[SDImageCodersManager sharedManager] encodedDataWithImage:image format:format options:nil]; } [self _storeImageDataToDisk:data forKey:key]; }
若是你正在跳槽或者正準備跳槽不妨動動小手,添加一下我們的交流羣1012951431來獲取一份詳細的大廠面試資料爲你的跳槽多添一份保障。