OC之runtime面試題(一)
阿新 • • 發佈:2020-12-30
對於LBPerson類,程式碼如下
@interface LBPerson : NSObject @property (nonatomic, copy) NSString *name; - (void)test; @end @implementation LBPerson - (void)test { NSLog(@"name = %@", self.name); } @end
外面存在以下呼叫程式碼,問能否呼叫成功,如果能列印結果是什麼
- (void)viewDidLoad { [super viewDidLoad]; NSString *test = @"hhhhh"; id cls = [LBPerson class]; void *obj = &cls; [(__bridge id)obj test]; }
執行之後列印結果如下:
name = hhhhh
從列印結果看,呼叫成功了,但是列印了viewDidLoad中test的變數的值
首先我們分析為什麼能呼叫成功,對於一般的LBPerson中test的呼叫:
LBPerson *person = [[LBPerson alloc] init];
[person test];
對於正常的person物件呼叫test的方式,是通過person物件的isa指標,找到LBPerson類進行呼叫的
對於[(__bridge id)obj test]的呼叫,對於上述程式碼的宣告obj->cls->[LBPerson class],在[obj test]呼叫過程中,會根據obj的指向,取出obj指向地址中前八個位元組,而obj指向cls剛好,cls八個位元組全部指向[LBPerson class],這也就是能呼叫成功的原因
下面分析列印結果,列印結果為name = hhhhh
上述程式碼中記憶體分配如下圖所示:
最終呼叫test 傳入的是cls的地址,而正常的person物件呼叫時候,取name的值的時候,是根據person物件的地址加八個位元組。obj呼叫的時候相當於在cls地址的基礎上加八個位元組,剛好是test變數的地址,所以列印的是test變數的值