iOS 京東電話面試總結

1.交互兩個方法的現實有什么風險?

2.方法簽名有什么作用?

3.id和NSObject ,instancetype的區(qū)別?

類方法中,以alloc或new開頭

實例方法中,以autorelease,init,retain或self開頭會返回一個方法所在類類型的對象,這些方法就被稱為是關聯返回類型的方法。換句話說,這些方法的返回結果以方法所在的類為類型。

非關聯返回類型 + (id)constructAnArray;? 根據Cocoa的方法命名規(guī)范,得到的返回類型就和方法聲明的返回類型一樣,是id。

+ (instancetype)constructAnArray;? 得到的返回類型和方法所在類的類型相同,是NSArray*!總結一下,instancetype的作用,就是使那些非關聯返回類型的方法返回所在類的類型!

instancetype和id區(qū)別 :

1.id在編譯的時候不能判斷對象的真實類型instancetype在編譯的時候可以判斷對象的真實類型

2.如果init方法的返回值是instancetype,那么將返回值賦值給一個其它的對象會報一個警告如果是在以前, init的返回值是id,那么將init返回的對象地址賦值給其它對象是不會報錯的

3.id可以用來定義變量, 可以作為返回值, 可以作為形參instancetype只能用于作為返回值

//err,expected a type - (void)setValue:(instancetype)value { //do something } 就是錯的,應該寫成:- (void)setValue:(id)value { //d

注意:以后但凡自定義構造方法, 返回值盡量使用instancetype, 不要使用id

總結一下,instancetype的作用,就是使那些非關聯返回類型的方法返回所在類的類型!

一、關聯返回類型(related result types)根據Cocoa的命名規(guī)則,滿足下述規(guī)則的方法:1、類方法中,以alloc或new開頭2、實例方法中,以autorelease,init,retain或self開頭會返回一個方法所在類類型的對象,這些方法就被稱為是關聯返回類型的方法。換句話說,這些方法的返回結果以方法所在的類為類型,說的有點繞口,請看下面的例子:

@interface NSObject

+ (id)alloc;

- (id)init;

@end

@interface NSArray : NSObject

@end?

當我們使用如下方式初始化NSArray時:NSArray *array = [[NSArray alloc] init];

照Cocoa的命名規(guī)則,語句[NSArray alloc] 的類型就是NSArray因為alloc的返回類型屬于關聯返回類型。同樣,[[NSArray alloc]init] 的返回結果也是NSArray。

1.NSObject包含了一些其他的方法,需要實現NSObject協議,可以用NSObject來表示id,但是不能用id來表示NSObject

3.id可以是任何對象,包括不是NSObject的對象

4.定義id的時候不需要*,而定義NSOject的時候需要。

第一種是最常用的,id是個指針,任意類型的指針。它簡單地申明了指向對象的指針,沒有給編譯器任何類型信息

第二種表示使用NSObject靜態(tài)類型不是所有的Foundation/Cocoa對象都繼承息NSObject,比如NSProxy就不從NSObject繼承,所以你無法使用NSObject*指向這個對象,即使NSProxy對象有release和retain這樣的通用方法。為了解決這個問題,你需要第3種定義

第三種: id<NSObject>告訴編譯器,你不關心對象是什么類型,但它必須遵守NSObject協議(protocol),編譯器就能保證所有賦值給id<NSObject>類型的對象都遵守NSObject協議(protocol)。所以你無法使用NSObject*指向這個對象,即使NSProxy對象有release和retain這樣的通用方法

總結:? ? 1、如果你不需要任何的類型檢查,使用id,它經常作為返回類型,也經常用于申明代理(delegate)類型。? ? 2、如果真的需要編譯器檢查,那你就考慮使用第2種或者第3種。? ? 3、第三種使用協議(protocol)的優(yōu)點是,它能指向NSProxy對象,而更常用的情況是,你只想知道某個對象遵守了哪個協議,而不用關心它是什么類型。

4.使用kvo什么時候移除監(jiān)聽(dealloc不能移除的情況)?

一般KVO奔潰的原因:

被觀察的對象銷毀掉了(被觀察的對象是一個局部變量)

觀察者被釋放掉了,但是沒有移除監(jiān)聽(如模態(tài)推出,push,pop等)

注冊的監(jiān)聽沒有移除掉,又重新注冊了一遍監(jiān)聽

觸發(fā)回調方法(這兒需要注意一點,在Person.m文件中如果賦值沒有通過setter方法或者是kvc,例如(_name = name)這個時候不會觸發(fā)kvc的回調方法,也就是說賦值必須得通過setter方法或者KVC賦值,才會觸發(fā)回調方法)

當觀察者不需要監(jiān)聽時,可以調用removeObserver:forKeyPath:方法將KVO移除。需要注意的是,調用removeObserver需要在觀察者消失之前,否則會導致Crash。

直接修改成員變量會觸發(fā)KVO么?不會觸發(fā)KVO因為,觸發(fā)KVO是因為,執(zhí)行set方法時候,調用?willChangeValueForKey?didChangeValueForKey?但是直接修改成員變量不會調用set方法

5.block里面會不會存在self為空的情況(weak strong的原理)?

1.block 內部創(chuàng)建的強引用,block 是不會持有它的,block 只持有外部的強應用

值得注意的是,在ARC下__block會導致對象被retain,有可能導致循環(huán)引用。而在MRC下,則不會retain這個對象,也不會導致循環(huán)引用

如果是在MRC模式下,使用__block修飾self,則此時block訪問被釋放的self,則會導致crash。

在MRC環(huán)境下,__block根本不會對指針所指向的對象執(zhí)行copy操作,而只是把指針進行的復制。而這一點往往是很多新手&老手所不知道的!

而在ARC環(huán)境下,對于聲明為__block的外部對象,在block內部會進行retain,以至于在block環(huán)境內能安全的引用外部對象,所以要謹防循環(huán)引用的問題!

- (void)testBlockRetainCycle { ClassA* objA = [[ClassA alloc] init];

__weak typeof(objA) weakObjA = objA; s

elf.myBlock = ^() {

__strong typeof(weakObjA) strongWeakObjA = weakObjA;

[strongWeakObjA doSomething]; };

objA.objA = self; }

注:此方法只能保證在block執(zhí)行期間對象不被釋放,如果對象在block執(zhí)行執(zhí)行之前已經被釋放了,該方法也無效。

6.什么是動態(tài)連接庫?

7.NSNull和nil的區(qū)別?

nil:指向一個對象的空指針? ??Nil:指向一個類的空指針,? ?

NULL:指向其他類型(如:基本類型、C類型)的空指針, 用于對非對象指針賦空值.

NSNull:在集合對象中,表示空值的對象.

NSNull在Objective-C中是一個類 .NSNull有 + (NSNull *)null; 單例方法.多用于集合(NSArray,NSDictionary)中值為空的對象.

NSArray *array = [NSArray arrayWithObjects: [[NSObject alloc] init], [NSNull null], @"aaa", nil, [[NSObject alloc] init], [[NSObject alloc] init], nil];NSLog(@"%ld", array.count);// 輸出 3,NSArray以nil結尾

8.Objective-C類能動態(tài)添加成員變量嗎?

不能。

因此一并討論。很多人在學到Category時都會有疑問,既然允許用Category給類增加方法和屬性,那為什么不允許增加成員變量?

在Objective-C提供的runtime函數中,確實有一個class_addIvar()函數用于給類添加成員變量,但是文檔中特別說明:This function may only be called after objc_allocateClassPair and before objc_registerClassPair. Adding an instance variable to an existing class is not supported.

意思是說,這個函數只能在“構建一個類的過程中”調用。一旦完成類定義,就不能再添加成員變量了。經過編譯的類在程序啟動后就被runtime加載,沒有機會調用addIvar。程序在運行時動態(tài)構建的類需要在調用objc_registerClassPair之后才可以被使用,同樣沒有機會再添加成員變量。

顯然,這樣做會帶來嚴重問題,為基類動態(tài)增加成員變量會導致所有已創(chuàng)建出的子類實例都無法使用。那為什么runtime允許動態(tài)添加方法和屬性,而不會引發(fā)問題呢?

因為方法和屬性并不“屬于”類實例,而成員變量“屬于”類實例。我們所說的“類實例”概念,指的是一塊內存區(qū)域,包含了isa指針和所有的成員變量。所以假如允許動態(tài)修改類成員變量布局,已經創(chuàng)建出的類實例就不符合類定義了,變成了無效對象。但方法定義是在objc_class中管理的,不管如何增刪類方法,都不影響類實例的內存布局,已經創(chuàng)建出的類實例仍然可正常使用。

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,664評論 1 32
  • 1.設計模式是什么? 你知道哪些設計模式,并簡要敘述?設計模式是一種編碼經驗,就是用比較成熟的邏輯去處理某一種類型...
    龍飝閱讀 2,302評論 0 12
  • 1.設計模式是什么? 你知道哪些設計模式,并簡要敘述? 設計模式是一種編碼經驗,就是用比較成熟的邏輯去處理某一種類...
    司馬DE晴空閱讀 1,477評論 0 7
  • 所謂“理通則法明”,把東西的本質摸清楚了建立在本質上的法則就好理解了。做事你不能沒有目標,有目標還不夠還要保證目標...
    愛黑啤的醉熊閱讀 415評論 0 0
  • 接上一節(jié),我們了解到簡簡單單的幾行代碼就可以寫出一個動畫,本節(jié)將進一步對IOS的純代碼UI開發(fā)做簡單的入門。 ...
    yuchu1900閱讀 2,402評論 1 1

友情鏈接更多精彩內容