Object-C基礎知識問答
一個區分度很大的面試題
考察一個面試者基礎咋樣,基本上問一個 @property 就夠了:
@property 後面可以有哪些修飾符?
- 執行緒安全的:
- atomic,nonatomic
- 訪問許可權的
- readonly,readwrite
- 記憶體管理(ARC)
- assign,strong,weak,copy
- 記憶體管理(MRC)
- assign,retain,copy
- 指定方法名稱
- setter=
- getter=
什麼情況使用 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
- 在使用字串和block的時候一般都使用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 屬性
- 這東西沒有研究過,請你幫我介紹一下好嗎?
每個人擅長的領域不一樣,我們一般會從簡歷上找自己寫擅長的技術聊,假如自己並不是很熟,最好別寫出來或扯出來,萬一面試官剛好非常精通這裡就露餡了。
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下,不顯示指定任何屬性關鍵字時,預設的關鍵字都有哪些?
- 對應基本資料型別預設關鍵字是
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呼叫都是一樣的.
[※※※※]runtime如何通過selector找到對應的IMP地址?(分別考慮類方法和例項方法)
- 每一個類物件中都一個方法列表,方法列表中記錄著方法的名稱,方法實現,以及引數型別,其實selector本質就是方法名稱,通過這個方法名稱就可以在方法列表中找到對應的方法實現.
[※※※※]使用runtime Associate方法關聯的物件,需要在主物件dealloc的時候釋放麼?
- 在ARC下不需要
- 在MRC中,對於使用retain或copy策略的需要
[※※※※※]objc中的類方法和例項方法有什麼本質區別和聯絡?
- 類方法
- 類方法是屬於類物件的
- 類方法只能通過類物件呼叫
- 類方法中的self是類物件
- 類方法可以呼叫其他的類方法
- 類方法中不能訪問成員變數
- 類方法中不定直接呼叫物件方法
- 例項方法
- 例項方法是屬於例項物件的
- 例項方法只能通過例項物件呼叫
- 例項方法中的self是例項物件
- 例項方法中可以訪問成員變數
- 例項方法中直接呼叫例項方法
- 例項方法中也可以呼叫類方法(通過類名)
[※※※※※]_objc_msgForward函式是做什麼的,直接呼叫它將會發生什麼?
- (動態方法解析)物件無法解析訊息後,先呼叫起所屬類的resolveInstanceMethod:(SEL)selector方法。(通常property 使用@dynamic屬性,然後實現resolveInstanceMethod,接收未實現的setter and getter方法,用class_addMethod實現動態繫結)
- (備援接受者)如果未能截獲會走forwardingtargetforselector。(我們無法通過此處處理訊息轉發)
- (完整的訊息轉發機制)forwardInvocation.(實現此方法時,如果發現呼叫操作不應該呦本類處理,則需要呼叫其超類的同名方法,繼承體系中的每個類都有機會呼叫次請求,直到NSObject.如果NSObject也沒有實現改方法,會繼續呼叫doesNotRecognizeSelector以丟擲異常)
[※※※※※]runtime如何實現weak變數的自動置nil?
1. 沒有研究過,你有研究過嗎,可以給我講講嗎?
2. 我猜系統會維護一個弱指標列表,當某個物件銷燬時候,它會把所有指向該物件的弱指標設定為nil
[※※※※※]能否向編譯後得到的類中增加例項變數?能否向執行時建立的類中新增例項變數?為什麼?
1. 沒有這麼用過,執行中好像有新增屬性方法. 你對這一塊有很深瞭解嗎,能給我講講嗎.
[※※※]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.如果沒有事件,就掛起,等有事件了,立即喚醒事件迴圈,開始執行.
[※]objc使用什麼機制管理物件記憶體?
* MRC 手動引用計數
* ARC 自動引用計數,現在通常使用自動引用計數
[※※※※]ARC通過什麼方式幫助開發者管理記憶體?
通過編譯器在編譯的時候,插入如內管理的程式碼
[※※※※]不手動指定autoreleasepool的前提下,一個autorealese物件在什麼時刻釋放?(比如在一個vc的viewDidLoad中建立)
在每次事件迴圈開始建立自動釋放池,在每次事件結束銷燬自動釋放池
以viewDidLoad方法為例,可以理解為在viewDidLoad方法開始執行之前建立自動釋放池,
在viewDidLoad方法執行之後銷燬自動釋放吃
runLoop.png
[※※※※]BAD_ACCESS在什麼情況下出現?
1. 死迴圈了
2. 訪問一個殭屍物件
[※※※※※]蘋果是如何實現autoreleasepool的?
1. 我猜想autoreleasepool 本質就是一個佇列(陣列),
2. 當呼叫autorelease的時候會把該物件新增到autoreleasepool中,並且把引用計數+1
3. 當autoreleasepool即將銷燬的時候,把其中的所有物件進行一次release操作
[※※]使用block時什麼情況會發生引用迴圈,如何解決?
只要是一個物件對該block進行了強引用,在block內部有直接使用到該物件,
[※※]在block內如何修改block外部變數?
- 通過 __bock修改的外部變數,可以在block內部修改
- 想裝B的話可以說一下__bock內部做了什麼事
[※※※]使用系統的某些block api(如UIView的block版本寫動畫時),是否也考慮引用迴圈問題?
一般不用考慮,因為官方文件中沒有告訴我們要注意發生強引用,所以推測系統控制元件一般沒有對這些block進行強引用,所以我們可以不用考慮迴圈強引用的問題
[※※]GCD的佇列(dispatch_queue_t)分哪兩種型別?
序列佇列和並行佇列
[※※※※]如何用GCD同步若干個非同步呼叫?(如根據若干個url非同步載入多張圖片,然後在都下載完成後合成一張整圖)
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
給這個value設定一個值,就可以觸發了
[※※※]若一個類有例項變數NSString *_foo,呼叫setValue:forKey:時,可以以foo還是_foo作為key?
都可以
[※※※※]KVC的keyPath中的集合運算子如何使用?
1. 必須用在集合物件上或普通物件的集合屬性上
2. 簡單集合運算子有@avg, @count , @max , @min ,@sum,
3. 格式 @"@sum.age"或 @"集合屬性[email protected]"
[※※※※]KVC和KVO的keyPath一定是屬性麼?
1.一個可以是成員變數
[※※※※※]如何關閉預設的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 物件
相關推薦
Object-C基礎知識問答
一個區分度很大的面試題 考察一個面試者基礎咋樣,基本上問一個 @property 就夠了: @property 後面可以有哪些修飾符? 執行緒安全的: atomic,nonatomic訪問許可權的 readonly,readwrite記憶體管理(ARC) assign
C#基礎知識-函數的定義和調用(五)
返回 {0} string 訪問修飾符 容器 列表 rdquo 所有 func 函數也可以稱為方法,可以很方便的把一些行為封裝到函數裏面,當調用這一函數時會把函數塊裏面的代碼按照順序執行,方法可以有多種形式,有無參數,有無返回值等。 1. 函數的定義 函數定
C#基礎知識-流程控制的應用(四)
相關 ats 循環 nbsp 使用 logs 嘗試 exc 設置斷點 流程控制我們在編程中運用到的地方非常的多,在上篇中僅僅只是簡單的介紹每一種的使用,並沒有運用到實例中,很難去理解它真正的作用。下面我們將實際的運用流程控制的代碼寫一些實例相關的程序,加深對流程控制的理解,
C#基礎知識-引用類型和值類型的區別(六)
值類型 type 調用 執行 new 內存堆 ada ont 不同類 在第一篇中我們介紹了C#中基本的15種數據類型,這15種數據類型中又分為兩大類,一種是值類型,一種是引用類型。值類型有sbyte、short、long、int、byte、ushort、uint、u
C#基礎知識-面向對象思想之繼承(八)
添加 電視劇 一中 一段 public bsp 更多 cnblogs tin 上一篇的標題編程思想我覺得不是很符合主題,因為編程思想的範圍太大了,不僅僅是封裝 繼承 多態,所以比較符合主題的應該是面向對象思想。這一篇中將繼續敘述面向對象思想中的繼承。 從字面來看繼承表達的意
C# 基礎知識
復制 運算 ren 必須 con -1 break 查找字符串 protected 一、運算符 1、運算符及算數表達式 +: 加法運算符 -: 減法運算符 *: 乘法運算符 /: 乘法
C# 基礎知識復習(一)
pri 字符 cati wid body 自增 tro ati system 一個 C# 程序主要包括以下部分: 命名空間聲明(Namespace declaration) 一個 class Class 方法 Class 屬性 一個 Main 方法 語句(Statemen
C# 基礎知識復習(三)---方法參數傳遞
val 相同 clas 沒有 tel cal 引用傳遞 局部變量 調用 一個方法是把一些相關的語句組織在一起,用來執行一個任務的語句塊。每一個 C# 程序至少有一個帶有 Main 方法的類。 要使用一個方法,您需要: 定義方法 調用方法 按值傳遞參數 這是參數傳遞
C#中(int)、Conver.Toint32()、int.Parse()三種類型轉換方式的區別與聯系--C#基礎知識
實例 文章 小數位 其他 返回 system roman static logs 自己也是剛學習C#程序設計語言,總結了一點知識點,想分享給大家。畢竟剛學習這門語言,學得不深,哪裏如果有錯誤,請幫個忙指出一下哈,謝謝! 1、(int)可用於單精度、雙精度等其他數值類型的轉
C# 基礎知識復習(五)---結構與枚舉
pre end test class ++ 產生 演示 初始 main 定義結構 為了定義一個結構,您必須使用 struct 語句。struct 語句為程序定義了一個帶有多個成員的新的數據類型。 例如,您可以按照如下的方式聲明 Book 結構: struct Books {
C# 基礎知識復習(六)---類
etl 標識符 c# namespace 函數 屬性 註意 cif 聲明 C# 類(Class) 當你定義一個類時,你定義了一個數據類型的藍圖。這實際上並沒有定義任何的數據,但它定義了類的名稱意味著什麽,也就是說,類的對象由什麽組成及在這個對象上可執行什麽操作。對象是類的
C# 基礎知識復習(十)---接口與接口繼承
實現繼承 -i tro 一點 格式 pub 類定義 接口類 lin 1.接口必須I開頭; 2.只有申明,沒有實現; 3.實現類在實現方法時,必須名字與接口一致; 4.實現類在實現繼承接口時,必須把父接口的方法一並實現; 5.接口申明,默認是public的,這一點與class
c#基礎知識(2)
alt 實現 height over 聯系 c# 覆蓋 tro strong 一,繼承與派生 原來的類——基類或父類 新定義的類——派生類 引入原因:擴展原有類的功能 派生類的成員: (1)會吸收基類的所有成員(包括私有成
C# 基礎知識-20---。NET程序的 排序列表 List<T> Hashtable
nbsp net com hash -- ima cnblogs ble .com C# 基礎知識-20---。NET程序的 排序列表 List<T> Hashtable
C# 基礎知識-07----.NET中Directory 和Path 類 和 Environment類
cto directory .com -- mage rec alt 基礎 path C# 基礎知識-07----.NET中Directory 和Path 類 和 Environment類
C# 基礎知識-08----.NET中FileStream 類 和 StreamReader類 和 BinaryRead 類
logs -1 cnblogs c# mage amr png .cn 基礎知識 C# 基礎知識-08----.NET中FileStream 類 和 StreamReader類 和 BinaryRead 類
C# 基礎知識-11---。NET正則表達式
9.png src -1 png .cn 則表達式 http com 。net C# 基礎知識-11---。NET正則表達式
c#基礎知識第五節
n) 基礎 ole 最大值 new rgs sys c# () 數組的定義 using System; class program { static void Main(sting [ ] args) { //定義一個int類型的數組x int
c#基礎知識第九節
類和對象 成員 public void 特征 pub ati args main 類和對象 class Dog { //共同特征,品種(字段) public string breed; //行為, 犬叫(方法)
c#基礎知識第十一節
var part 包括 introduce new 構造 bsp private 根據 析構方法 和構造方法相反。 class person { public string Name { get;