美文网首页
iOS面试关于runtime

iOS面试关于runtime

作者: 指尖猿 | 来源:发表于2023-06-17 01:59 被阅读0次

现在面试说几句就离不开Runtime,下面我将写一些简单的Runtime的概念,一方面复习巩固知识,另一方面希望读者能够有所收获。

Runtime是Objective-C中非常强大和灵活的运行时系统,它提供了一组API来动态地创建、修改、查询类和对象,支持消息发送、方法交换、动态添加方法等高级特性。下面,我们将以实际代码案例的形式,介绍Runtime的具体用法。

动态添加方法

动态添加方法是Runtime的一个重要特性之一,它允许我们在运行时动态地为一个类添加新的方法。下面是一个简单的例子:

#import <objc/runtime.h>

@interface MyClass : NSObject

@end

@implementation MyClass

@end

void dynamicMethodIMP(id self, SEL _cmd)
{
    NSLog(@"添加的方法已经被调用");
}

int main(int argc, char * argv[]) {
    @autoreleasepool {
        
        MyClass *myClass = [[MyClass alloc] init];
        
        class_addMethod([myClass class], @selector(dynamicMethod), (IMP) dynamicMethodIMP, "v@:");
        
        if ([myClass respondsToSelector:@selector(dynamicMethod)]) {
            [myClass performSelector:@selector(dynamicMethod)];
        } else {
            NSLog(@"方法未被添加");
        }
    }
    return 0;
}

在这个例子中,我们首先定义了一个MyClass类,并在运行时动态地为它添加了一个名为dynamicMethod的方法。我们使用class_addMethod函数来添加方法,它需要传入一个类对象、一个方法选择器、一个方法的实现和一个方法签名。在这个例子中,我们使用了一个名为dynamicMethodIMP的函数作为方法的实现,它打印一条消息。最后,我们通过检查对象是否响应dynamicMethod方法来判断方法是否已经被添加,并使用performSelector方法来调用它。

方法交换

方法交换是Runtime的另一个重要特性,它允许我们在运行时动态地交换两个方法的实现。下面是一个简单的例子:

#import <objc/runtime.h>

@interface MyClass : NSObject

- (void)originalMethod;

@end

@implementation MyClass

- (void)originalMethod {
    NSLog(@"原始方法已经被调用");
}

@end

@implementation MyClass (Category)

- (void)swizzledMethod {
    NSLog(@"交换后的方法已经被调用");
    [self swizzledMethod];
}

@end

int main(int argc, char * argv[]) {
    @autoreleasepool {
        
        MyClass *myClass = [[MyClass alloc] init];
        
        Method originalMethod = class_getInstanceMethod([MyClass class], @selector(originalMethod));
        Method swizzledMethod = class_getInstanceMethod([MyClass class], @selector(swizzledMethod));
        method_exchangeImplementations(originalMethod, swizzledMethod);
        
        [myClass originalMethod];
    }
    return 0;
}

在这个例子中,我们首先定义了一个MyClass类,并在它的Category中添加了一个名为swizzledMethod的方法。我们使用method_exchangeImplementations函数来交换originalMethod和swizzledMethod的实现。最后,我们使用originalMethod方法来调用原始的方法,但实际上它会调用被交换后的swizzledMethod。

消息转发

消息转发是Runtime的另一个重要特性,它允许我们在运行时处理未知消息或方法。下面是一个简单的例子:

#import <objc/runtime.h>

@interface MyClass : NSObject

@end

@implementation MyClass

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    NSLog(@"消息转发已经被触发");
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}

@end

int main(int argc, char * argv[]) {
    @autoreleasepool {
        
        MyClass *myClass = [[MyClass alloc] init];
        
        [myClass performSelector:@selector(unknownMethod)];
    }
    return 0;
}

在这个例子中,我们首先定义了一个MyClass类,并重写了forwardInvocation和methodSignatureForSelector方法。当对象收到一个未知的消息时,它会触发forwardInvocation方法。我们还需要重写methodSignatureForSelector方法来返回一个合法的方法签名,这是消息转发的必要步骤。最后,我们使用performSelector方法来调用一个名为unknownMethod的未知方法,这会触发消息转发机制并调用forwardInvocation方法。

上述代码案例展示了Runtime的一些常用特性和API的用法,包括动态添加方法、方法交换和消息转发,献丑了各位。

相关文章

网友评论

      本文标题:iOS面试关于runtime

      本文链接:https://www.haomeiwen.com/subject/unrdydtx.html