1. 程式人生 > 實用技巧 >OC之runtime面試題(一)

OC之runtime面試題(一)

對於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變數的值