专注iOS开发的小渣渣

经典面试题分析(一)

2020-09-17  本文已影响0人  Henry________

几道isa相关的经典面试题以及分析

前期准备:

@interface HRTest : NSObject
    - (void)sayHello;
    + (void)sayHappy;
@end

方法归属相关测试

第一道

HRTest *test = [HRTest alloc];
        Class pClass     = object_getClass(test);

const char *className = class_getName(pClass);
    Class metaClass = objc_getMetaClass(className); //原类
    
    Method method1 = class_getInstanceMethod(pClass, @selector(sayHello));
    Method method2 = class_getInstanceMethod(metaClass, @selector(sayHello));

    Method method3 = class_getInstanceMethod(pClass, @selector(sayHappy));
    Method method4 = class_getInstanceMethod(metaClass, @selector(sayHappy));
    
    NSLog(@"%p-%p-%p-%p",method1,method2,method3,method4);

输出结果:

第二道

const char *className = class_getName(pClass);
    Class metaClass = objc_getMetaClass(className); //元类
    
    Method method1 = class_getClassMethod(pClass, @selector(sayHello));
    Method method2 = class_getClassMethod(metaClass, @selector(sayHello));

    Method method3 = class_getClassMethod(pClass, @selector(sayHappy));
    Method method4 = class_getClassMethod(metaClass, @selector(sayHappy));
    
    NSLog(@"%s-%p-%p-%p-%p",__func__,method1,method2,method3,method4);

输出结果:


class_getClassMethod的方法实现
Method class_getClassMethod(Class cls, SEL sel)
{
    if (!cls  ||  !sel) return nil;

    return class_getInstanceMethod(cls->getMeta(), sel);
}

Class getMeta() {
    if (isMetaClass()) return (Class)this;
    else return this->ISA();
}
小总结

实例方法存在类中,类方法存在元类中。

第三道

IMP imp1 = class_getMethodImplementation(pClass, @selector(sayHello));
    IMP imp2 = class_getMethodImplementation(metaClass, @selector(sayHello));
    IMP imp3 = class_getMethodImplementation(pClass, @selector(sayHappy));
    IMP imp4 = class_getMethodImplementation(metaClass, @selector(sayHappy));
IMP class_getMethodImplementation(Class cls, SEL sel)
{
    IMP imp;
    if (!cls  ||  !sel) return nil;
    imp = lookUpImpOrNil(nil, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER);   //先找缓存cache_t,然后去cls->data()->methods()中查找
    if (!imp) {
        return _objc_msgForward;    //找不到回到这里
    }
    return imp;
}
0x100001d00-0x7fff6c018580-0x7fff6c018580-0x100001d30

(lldb) p/x imp1
(IMP) $0 = 0x0000000100001d00 (002-类方法归属分析`-[LGPerson sayHello] at LGPerson.m:13)

(lldb) p/x imp4
(IMP) $1 = 0x0000000100001d30 (002-类方法归属分析`+[LGPerson sayHappy] at LGPerson.m:17)

(lldb) p/x imp2
(IMP) $2 = 0x00007fff6c018580 (libobjc.A.dylib`_objc_msgForward)

第四道

BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];   
        BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]]; 
        BOOL re3 = [(id)[HRTest class] isKindOfClass:[HRTest class]];  
        BOOL re4 = [(id)[HRTest class] isMemberOfClass:[HRTest class]];

输出结果:


+ (BOOL)isKindOfClass:(Class)cls {
    //使用调用者的isa和当前入参对比。
    for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

循环:
第一步:NSObject的isa -> 根元类
第二步:根元类的superclass -> NSObject
所以第一个相等;HRTest的isa->superclass指向根源类并不相等

+ (BOOL)isMemberOfClass:(Class)cls {
    return self->ISA() == cls;
}

拿当前类的isa指向和参数做对比,相同的类一定不相等.

第五道

BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];       //
        BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];     //
        BOOL re7 = [(id)[HRTest alloc] isKindOfClass:[LGPerson class]];       //
        BOOL re8 = [(id)[HRTest alloc] isMemberOfClass:[LGPerson class]]; 
- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}
- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

这道题很简单,现实面试应该是碰不到这样的题目。

上一篇下一篇

猜你喜欢

热点阅读