標籤:write ons 產生 自訂 bullet 個人 跳過 nsstring 屬性
李洪強iOS經典面試題30-一個區分度很大的面試題
考察一個面試者基礎咋樣,基本上問一個 @property 就夠了:
@property 後面可以有哪些修飾符?
- 安全執行緒的:
- 存取權限的
- 記憶體管理(ARC)
- 記憶體管理(MRC)
- 指定方法名稱
什麼情況使用 weak 關鍵字,相比 assign 有什麼不同?比如:
- 在ARC中,出現循環參考的時候,必須要有一端使用weak,比如:自訂View的代理屬性
- 已經自身已經對它進行一次強應用,沒有必要在強引用一次,此時也會使用weak,自訂View的子控制項屬性一般也使用weak;但b是也可以使用strong
- weak當對象銷毀的時候,指標會被自動化佈建為nil,而assign不會* assigin 可以用非OC對象,而weak必須用於OC對象
怎麼用 copy 關鍵字?
- 對於字串和block的屬性一般使用copy
- 字串使用copy是為了外部把字串內容改了,影響該屬性
- block使用copy是在MRC遺留下來的,在MRC中,方法內部的block是在在棧區的,使用copy可以把它放到堆區.在ACR中對於block使用copy還是strong效果是一樣的
這個寫法會出什麼問題: @property (copy) NSMutableArray *array;
- 添加,刪除,修改數組內的元素的時候,程式會因為找不到對於的方法而崩潰.因為copy就是複製一個不可變NSArray的對象
如何讓自己的類用 copy 修飾符?
- 你是說讓我的類也支援copy的功能嗎?
- 如果面試官說是:
- 遵守NSCopying協議
- 實現 - (id)copyWithZone:(NSZone *)zone; 方法
- 如果面試官說否,是屬性中如何使用copy
如何重寫帶 copy 關鍵字的 setter?
- 重寫copy的setter方法時候,一定要調用一下傳入的對象的copy方法,然後在賦值給該setter的方法對應的成員變數
這一套問題區分度比較大,如果上面的問題都能回答正確,可以延伸問更深入點的:@property 的本質是什嗎?ivar、getter、setter 是如何產生並添加到這個類中的
- 在普通的OC對象中,@property就是編譯其自動幫我們產生一個私人的成員變數和setter與getter方法的聲明和實現
- 我為了搞清屬性是怎麼實現的,曾經反編譯過相關的代碼,他大致產生了五個個東西
- OBJC_IVAR_$類名$屬性名稱 該屬性的位移量
- setter與getter方法對應的實現函數
- ivar_list 就是成員變數列表
- method_list 方法列表
- prop_list 屬性列表
也就是說我們每次在增加一個屬性,系統都會在ivar_list中添加一個成員變數的描述,在method_list中增加setter與getter方法的描述,在屬性列表中增加一個屬性的屬性的描述,然後計算該屬性在對象中的位移量,然後伸出setter與getter方法對應的實現,在setter方法方法中從位移量的位置開始賦值,在getter方法中從位移量開始取值,為了能夠讀取正確位元組數,系統對象位移量的指標類型進行了類型強轉.
@protocol 和 category 中如何使用 @property
- 在protocol中使用property只會產生setter和getter方法聲明,我們使用屬性的目的,是希望遵守我協議的對象的實現該屬性
- category 使用 @property 也是只會產生setter和getter方法的聲明,如果我們真的需要給category增加屬性的實現,需要藉助於運行時的兩個函數
- objc_setAssociatedObject
- objc_getAssociatedObject
runtime 如何? weak 屬性
runtime 對註冊的類, 會進行布局,對於 weak 對象會放入一個 hash 表中。 用 weak 指向的對象地址作為 key,當此對象的引用計數為0的時候會 dealloc, 進而在這個 weak 表中找到此對象地址為鍵的所有 weak 對象,從而設定為 nil
每個人擅長的領域不一樣,我們一般會從簡曆上找自己寫擅長的技術聊,假如自己並不是很熟,最好別寫出來或扯出來,萬一面試官剛好非常精通這裡就露餡了。
Checklist
總結過些面試題,沒堅持下去,後來把這些當 checklist,面試的時候實在沒話聊的時候做個提醒,語言、架構、運行機制性質的:
[※]@property中有哪些屬性關鍵字?
同上
[※]weak屬性需要在dealloc中置nil嗎?
不需要,在ARC環境無論是強指標還是弱指標都無需在deallco設定為nil,ARC會自動幫我們處理
[※※]@synthesize和@dynamic分別有什麼作用?
- @property有兩個對應的詞,一個是@synthesize,一個是@dynamic。如果@synthesize和@dynamic都沒寫,那麼預設的就是@syntheszie var = _var;
- @synthesize的語義是如果你沒有手動實現setter方法和getter方法,那麼編譯器會自動為你加上這兩個方法。
- @dynamic告訴編譯器,屬性的setter與getter方法由使用者自己實現,不自動產生。(當然對於readonly的屬性只需提供 getter即可)。假如一個屬性被聲明為@dynamic var,然後你沒有提供@setter方法和@getter方法,編譯的時候沒問題,但是當程式運行到instance.var =someVar,由於缺setter方法會導致程式崩潰;或者當運行到 someVar = var時,由於缺getter方法同樣會導致崩潰。編譯時間沒問題,運行時才執行相應的方法,這就是所謂的動態綁定。
[※※※]ARC下,不顯示指定任何屬性關鍵字時,預設的關鍵字都有哪些?
- 對應基礎資料型別 (Elementary Data Type)預設關鍵字是
atomic,readwrite,assign
- 對於普通的OC對象
atomic,readwrite,strong
[※※※]用@property聲明的NSString(或NSArray,NSDictionary)經常使用copy關鍵字,為什嗎?如果改用strong關鍵字,可能造成什麼問題?
- 因為父類指標可以指向子類對象,使用copy的目的是為了讓本對象的屬性不受外界影響,使用copy無論給我傳入是一個可變對象還是不可對象,我本身持有的就是一個不可變的副本.
- 如果我們使用是strong,那麼這個屬性就有可能指向一個可變對象,如果這個可變對象在外部被修改了,那麼會影響該屬性.
[※※※]@synthesize合成執行個體變數的規則是什嗎?假如property名為foo,存在一個名為_foo的執行個體變數,那麼還會自動合成新變數嗎?
如果沒有指定成員變數的名稱與自動產生一個屬性同名的成員變數,如果指定的成員變數的名稱,會產生一個指定的名稱的成員變數,如果這個成員已經存在了就不再產生了.
如果是 @synthesize foo; 還會產生一個名稱為foo的成員變數
如果是 @synthesize foo = _foo; 就不會產生成員變數了.
[※※※※※]在有了自動合成屬性執行個體變數之後,@synthesize還有哪些使用情境?
@synthesize主要就是用來產生setter,getter方法的實現,在@property被增強之後,其實已經很少使用@synthesize了,你知道@synthesize的其他使用情境嗎? 能給我介紹一下嗎?
如果你聽懂了,感覺面試官說的很有道理,可以說點讚美的話.
[※※]objc中向一個nil對象發送訊息將會發生什嗎?
- 在Objective-C中向nil發送訊息是完全有效——只是在運行時不會有任何作用:
- 如果一個方法傳回值是一個對象,那麼發送給nil的訊息將返回0(nil)。例如:Person * motherInlaw = [ aPerson spouse] mother];如果spouse對象為nil,那麼發送給nil的訊息mother也將返回nil。
- 如果方法傳回值為指標類型,其指標大小為小於或者等於sizeof(void*),float,double,long double 或者long long的整型標量,發送給nil的訊息將返回0。
- 如果方法傳回值為結構體,發送給nil的訊息將返回0。結構體中各個欄位的值將都是0。
- 如果方法的傳回值不是上述提到的幾種情況,那麼發送給nil的訊息的傳回值將是未定義的。
[※※※]objc中向一個對象發送訊息[obj foo]和objc_msgSend()函數之間有什麼關係?
該方法編譯之後就是objc_msgSend()函數調用.如果我沒有記錯的大概是這樣的.
((void ()(id, SEL))(void )objc_msgSend)((id)obj, sel_registerName("foo"));
[※※※]什麼時候會報unrecognized selector的異常?
- 當該對象上某個方法,而該對象上沒有實現這個方法的時候[※※※※]一個objc對象如何進行記憶體布局?(考慮有父類的情況)
- 所有父類的成員變數和自己的成員變數都會存放在該對象所對應的儲存空間中.
- 每一個對象內部都一個isA指標,指向他的類對象,類對象中存放著本對象的對象方法列表和成員變數的列表,屬性列表,它內部也有一個isA指標指向元對象(meta class),元對象內部存放的是類方法列表,類對象內部還有一個superclass的指標,指向他的父類對象
- 根對象就是NSobject
- :
[※※※※]一個objc對象的isa的指標指向什嗎?有什麼作用?
[※※※※]下面的代碼輸出什嗎?
@implementation Son : Father- (id)init{ self = [super init]; if (self) { NSLog(@"%@", NSStringFromClass([self class])); NSLog(@"%@", NSStringFromClass([super class])); } return self;}@end
輸出的結果都是:Son,
原因:super 和 self 都是指向的本執行個體對象的,
不同的是,super調用的跳過本類方法,調用父類的方法
父類方法的class方法本來都是在基類中實現的,所以無論使用self和super調用都是一樣的.
具體分析參照刨根問底Objective-C Runtime(1)- Self & Super
[※※※※]runtime如何通過selector找到對應的IMP地址?(分別考慮類方法和執行個體方法)
- 每一個類對象中都一個方法列表,方法列表中記錄著方法的名稱,方法實現,以及參數類型,其實selector本質就是方法名稱,通過這個方法名稱就可以在方法列表中找到對應的方法實現.
[※※※※]使用runtime Associate方法關聯的對象,需要在主對象dealloc的時候釋放嗎?
- 在ARC下不需要
- 在MRC中,對於使用retain或copy策略的需要
[※※※※※]objc中的類方法和執行個體方法有什麼本質區別和聯絡?
- 類方法
- 類方法是屬於類對象的
- 類方法只能通過類對象調用
- 類方法中的self是類對象
- 類方法可以調用其他的類方法
- 類方法中不能訪問成員變數
- 類方法中不定直接調用對象方法
- 執行個體方法
- 執行個體方法是屬於執行個體對象的
- 執行個體方法只能通過執行個體對象調用
- 執行個體方法中的self是執行個體對象
- 執行個體方法中可以訪問成員變數
- 執行個體方法中直接調用執行個體方法
- 執行個體方法中也可以調用類方法(通過類名)
[※※※※※]_objc_msgForward函數是做什麼的,直接調用它將會發生什嗎?
- 沒喲研究過,從名字來看是用來轉寄訊息的,你能給我講講嗎?謝謝!
[※※※※※]runtime如何?weak變數的自動置nil?
1. 沒有研究過,你有研究過嗎,可以給我講講嗎?2. 我猜系統會維護一個弱指標列表,當某個對象銷毀時候,它會把所有指向該對象的弱指標設定為nil
[※※※※※]能否向編譯後得到的類中增加執行個體變數?能否向運行時建立的類中添加執行個體變數?為什嗎?
因為編譯後的類已經註冊在 runtime 中,類結構體中的 objc_ivar_list 執行個體變數的鏈表 和 instance_size 執行個體變數的記憶體大小已經確定,同時runtime 會調用 class_setIvarLayout 或 class_setWeakIvarLayout 來處理 strong weak 引用。所以不能向存在的類中添加執行個體變數,運行時建立的類是可以添加執行個體變數,調用 class_addIvar 函數。但是得在調用 objc_allocateClassPair 之後,objc_registerClassPair 之前,原因同上。
[※※※]runloop和線程有什麼關係?
1. 每一個線程中都一個runloop,只有主線的的runloop預設是開啟的,其他線程的runloop是預設沒有開啟的 2. 可以通過CFRunLoopRun() 函數來開啟一個事件迴圈 3. 看SDWebImage源碼的時候見到有這麼用過.
[※※※]runloop的mode作用是什嗎?
model 主要是用來指定時間在運行迴圈中的優先順序的
蘋果公開提供的 Mode 有兩個:
kCFRunLoopDefaultMode
kCFRunLoopCommonModes
如果我們把一個NSTimer對象以kCFRunLoopDefaultMode添加到主運行迴圈中的時候,當一直有使用者事件處理的時候,NSTimer將不再被調度
如果我們把一個NSTimer對象以kCFRunLoopCommonModes添加到主運行迴圈中的時候,當一直有使用者事件處理的時候,NSTimer還能正常的調度,互不影響.
[※※※※]以+ scheduledTimerWithTimeInterval...的方式觸發的timer,在滑動頁面上的列表時,timer會暫訂回調,為什嗎?如何解決?
同上
[※※※※※]猜想runloop內部是如何?的?
1. 他是一個死迴圈 2.如果事件隊列中存放在事件,那就取出事件,執行相關代碼 3.如果沒有事件,就掛起,等有事件了,立即喚醒事件迴圈,開始執行. 簡單來說。。。function loop() { initialize(); do { var message = get_next_message(); process_message(message); } while (message != quit);}
[※]objc使用什麼機制管理對象記憶體?
* MRC 手動引用計數* ARC 自動引用計數,現在通常使用自動引用計數
[※※※※]ARC通過什麼方式協助開發人員管理記憶體?
通過編譯器在編譯的時候,插入如內管理的代碼
[※※※※]不手動指定autoreleasepool的前提下,一個autorealese對象在什麼時刻釋放?(比如在一個vc的viewDidLoad中建立)
在每次事件迴圈開始建立自動釋放池,在每次事件結束銷毀自動釋放池以viewDidLoad方法為例,可以理解為在viewDidLoad方法開始執行之前建立自動釋放池,在viewDidLoad方法執行之後銷毀自動釋放吃
[※※※※]BAD_ACCESS在什麼情況下出現?
1. 死迴圈了2. 訪問一個殭屍對象
[※※※※※]蘋果是如何?autoreleasepool的?
1. 我猜想autoreleasepool 本質就是一個隊列(數組),2. 當調用autorelease的時候會把該對象添加到autoreleasepool中,並且把引用計數+13. 當autoreleasepool即將銷毀的時候,把其中的所有對象進行一次release操作
[※※]使用block時什麼情況會發生引用迴圈,如何解決?
只要是一個對象對該block進行了強引用,在block內部有直接使用到該對象,
[※※]在block內如何修改block外部變數?
- 通過 __bock修改的外部變數,可以在block內部修改
- 想裝B的話可以說一下__bock內部做了什麼事
[※※※]使用系統的某些block api(如UIView的block版本寫動畫時),是否也考慮引用迴圈問題?
一般不用考慮,因為官方文檔中沒有告訴我們要注意發生強引用,所以推測系統控制項一般沒有對這些block進行強引用,所以我們可以不用考慮迴圈強引用的問題
[※※]GCD的隊列(dispatch_queue_t)分哪兩種類型?
串列隊列和並行隊列
[※※※※]如何用GCD同步若干個非同步呼叫?(如根據若干個url非同步載入多張圖片,然後在都下載完成後合成一張整圖)
總體上說: 使用 dispatch group,然後 wait forever 等待完成, 或者採取 group notify 來通知回調。 細節: 1. 建立非同步隊列 2. 建立dispatch_group dispatch_group_t = dispatch_group_create() 3. 通過組來執行非同步下載任務 dispatch_group_async(queueGroup, aQueue, ^{ NSLog(@"下載圖片."); }); 4.等到所有任務完成 dispatch_group_wait(queueGroup, DISPATCH_TIME_FOREVER); 5.合成圖片
[※※※※]dispatch_barrier_async的作用是什嗎?
barrier:是障礙物的意思,在多個並行任務中間,他就像是一個隔離帶,把前後的並行任務分開.dispatch_barrier_async 作用是在並行隊列中,等待前面操作並行任務完成再執行dispatch_barrier_async中的任務,如果後面還有並行任務,會開始執行後續的並行任務
[※※※※※]蘋果為什麼要廢棄dispatch_get_current_queue?
容易誤用造成死結
[※※※※※]以下代碼運行結果如何?
- (void)viewDidLoad{ [super viewDidLoad]; NSLog(@"1"); dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"2"); }); NSLog(@"3");}
- 只能輸出1,然後線程主線程死結
[※※]addObserver:forKeyPath:options:context:各個參數的作用分別是什麼,observer中需要實現哪個方法才能獲得KVO回調?
// 添加索引值觀察 /** 1. 調用對象:要監聽的對象 2. 參數 1> 觀察者,負責處理監聽事件的對象 2> 觀察的屬性 3> 觀察的選項 4> 上下文 */ [self.person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:@"Person Name"];
// NSObject 分類方法,意味著所有的 NSObject 都可以實現這個方法!// 跟協議的方法很像,分類方法又可以稱為“隱式代理”!不提倡用,但是要知道概念!// 所有的 kvo 監聽到事件,都會調用此方法/** 1. 觀察的屬性 2. 觀察的對象 3. change 屬性變化字典(新/舊) 4. 上下文,與監聽的時候傳遞的一致 可以利用上下文區分不同的監聽! */- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { NSLog(@"睡會 %@", [NSThread currentThread]); [NSThread sleepForTimeInterval:1.0]; NSLog(@"%@ %@ %@ %@", keyPath, object, change, context);}
[※※※]如何手動觸發一個value的KVO
1.通過setValue:forKey: 給屬性賦值2.通過setValue:forKeyPath: 給屬性賦值3.直接調用setter方法方法給屬性賦值4.直接通過指標給屬性賦值5.給這個value設定一個值,就可以觸發了
[※※※]若一個類有執行個體變數NSString *_foo,調用setValue:forKey:時,可以以foo還是_foo作為key?
都可以
[※※※※]KVC的keyPath中的集合運算子如何使用?
1. 必須用在集合對象上或普通對象的集合屬性上2. 簡單集合運算子有@avg, @count , @max , @min ,@sum,3. 格式 @"@sum.age"或 @"集合屬性.@max.age"
[※※※※]KVC和KVO的keyPath一定是屬性嗎?
1.一個可以是成員變數
[※※※※※]如何關閉預設的KVO的預設實現,並進入自訂的KVO實現?
如何自己動手實現 KVO
[※※※※※]apple用什麼方式實現對一個對象的KVO?
同上
[※※]IBOutlet連出來的視圖屬性為什麼可以被設定成weak?
因為視圖已經對它有一個強引用了
[※※※※※]IB中User Defined Runtime Attributes如何使用?
User Defined Runtime Attributes 是一個不被看重但功能非常強大的的特性, 它能夠通過KVC的方式配置一些你在interface builder 中不能配置的屬性。當你希望在IB中作儘可能多得事情, 這個特效能夠協助你編寫更加輕量級的viewcontroller
[※※※]如何調試BAD_ACCESS錯誤
1.設定全域斷點快速定位問題代碼所在行
[※※※]lldb(gdb)常用的調試命令?
最常用就是 : po 對象
李洪強iOS經典面試題30-一個區分度很大的面試題