OC最实用的runtime总结,面试、工作你看我就足够了!
引言
Objective-C是一门面向对象的编程语言,在iOS开发中被广泛使用。而在Objective-C中,runtime是其核心之一,为开发者提供了许多强大的特性。本文将总结OC中最实用的runtime特性,包括动态添加方法、动态交换方法、获取类的属性和方法列表、动态创建类和对象等,并结合实际案例演示其用法,帮助读者更好地理解和应用runtime。

1. 动态添加方法
在OC中,我们可以使用runtime动态地为一个类添加方法。这在某些情况下非常有用,比如在运行时根据条件来决定是否添加某个方法,或者在运行时根据用户的操作来动态添加方法。
步骤
导入
<objc/runtime.h>
头文件。使用
class_addMethod
函数为类添加方法。
代码示例
假设我们有一个Person类,但是它没有一个sayHello
方法。我们可以使用runtime在运行时动态为Person类添加一个sayHello
方法。
\#import <objc/runtime.h>
@interface Person : NSObject
@end
@implementation Person
@end
void sayHello(id self, SEL _cmd) {
NSLog(@"Hello!");
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
• Person *person = [[Person alloc] init];
• // 动态添加sayHello方法
• class_addMethod([Person class], @selector(sayHello), (IMP)sayHello, "v@:");
• // 调用动态添加的sayHello方法
• [person performSelector:@selector(sayHello)];
}
return 0;
}
运行这段代码,我们会发现Person类成功地动态添加了sayHello
方法,并成功调用了它。
2. 动态交换方法
使用runtime,我们还可以动态交换两个方法的实现。这在某些情况下非常有用,比如在调试或者实现A/B测试时,我们可能需要替换某个方法的实现。
步骤
导入
<objc/runtime.h>
头文件。使用
method_exchangeImplementations
函数交换两个方法的实现。
代码示例
假设我们有一个Calculator类,它有两个方法add:(NSInteger)a to:(NSInteger)b
和subtract:(NSInteger)a from:(NSInteger)b
,我们可以使用runtime在运行时交换这两个方法的实现。
#import <objc/runtime.h>
@interface Calculator : NSObject
- (NSInteger)add:(NSInteger)a to:(NSInteger)b;
- (NSInteger)subtract:(NSInteger)a from:(NSInteger)b;
@end
@implementation Calculator
- (NSInteger)add:(NSInteger)a to:(NSInteger)b {
return a + b;
}
- (NSInteger)subtract:(NSInteger)a from:(NSInteger)b {
return b - a;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
• Calculator *calculator = [[Calculator alloc] init];
• NSInteger result1 = [calculator add:5 to:10];
• NSLog(@"Result1: %ld", (long)result1); // Output: Result1: 15
•
• // 动态交换add:to:和subtract:from:方法的实现
• Method addMethod = class_getInstanceMethod([Calculator class], @selector(add:to:));
• Method subtractMethod = class_getInstanceMethod([Calculator class], @selector(subtract:from:));
• method_exchangeImplementations(addMethod, subtractMethod);
•
• NSInteger result2 = [calculator add:5 to:10];
• NSLog(@"Result2: %ld", (long)result2); // Output: Result2: 5
}
return 0;
}
在上述代码中,我们成功地动态交换了add:to:
和subtract:from:
方法的实现,从而在运行时改变了方法的行为。
3. 获取类的属性和方法列表
使用runtime,我们可以在运行时获取一个类的属性列表和方法列表,这为我们提供了更多的灵活性和动态性。
步骤
导入
<objc/runtime.h>
头文件。使用
class_copyPropertyList
函数获取类的属性列表。使用
class_copyMethodList
函数获取类的方法列表。
代码示例
假设我们有一个Person类,我们可以使用runtime在运行时获取它的属性列表和方法列表。
#import <objc/runtime.h>
@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger age;
- (void)sayHello;
@end
@implementation Person
- (void)sayHello {
NSLog(@"Hello, my name is %@ and I am %ld years old.", self.name, (long)self.age);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
• Person *person = [[Person alloc] init];
• person.name = @"John";
• person.age = 30;
•
• // 获取属性列表
• unsigned int propertyCount;
• objc_property_t *properties = class_copyPropertyList([Person class], &propertyCount);
• for (unsigned int i = 0; i < propertyCount; i++) {
• objc_property_t property = properties[i];
• const char *propertyName = property_getName(property);
• NSString *name = [NSString stringWithUTF8String:propertyName];
• NSLog(@"Property: %@", name);
• }
• free(properties);
•
• // 获取方法列表
• unsigned int methodCount;
• Method *methods = class_copyMethodList([Person class], &methodCount);
• for (unsigned int i = 0; i < methodCount; i++) {
• Method method = methods[i];
• SEL methodName = method_getName(method);
• NSString *name = NSStringFromSelector(methodName);
• NSLog(@"Method: %@", name);
• }
• free(methods);
}
return 0;
}
在上述代码中,我们成功地获取了Person类的属性列表和方法列表,并输出了它们的名称。
4. 动态创建类和对象
在runtime中,我们还可以动态地创建类和对象。这在一些需要动态生成类和对象的场景下非常有用,比如在运行时根据用户的操作动态生成新的类和对象。
步骤
导1. 导入
<objc/runtime.h>
头文件。使用
objc_allocateClassPair
函数创建一个新类。使用
class_addMethod
函数为新类添加方法。使用
objc_registerClassPair
函数注册新类。使用
class_createInstance
函数创建新类的实例。
代码示例
假设我们需要在运行时动态创建一个新的Person类,并为该类添加一个sayHello
方法。
#import <objc/runtime.h>
@interface Person : NSObject
@end
@implementation Person
@end
void sayHello(id self, SEL _cmd) {
NSLog(@"Hello, I am a dynamic Person!");
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
• // 动态创建一个新的Person类
• Class newClass = objc_allocateClassPair([NSObject class], "DynamicPerson", 0);
•
• // 为新类添加sayHello方法
• class_addMethod(newClass, @selector(sayHello), (IMP)sayHello, "v@:");
•
• // 注册新类
• objc_registerClassPair(newClass);
•
• // 创建新类的实例并调用sayHello方法
• id dynamicPerson = [[newClass alloc] init];
• [dynamicPerson performSelector:@selector(sayHello)];
}
return 0;
}
在上述代码中,我们成功地动态创建了一个名为DynamicPerson的新类,并为其添加了sayHello
方法。最后,我们创建了DynamicPerson类的实例,并成功调用了sayHello
方法。
结论
OC的runtime是iOS开发中非常强大且实用的特性,它为开发者提供了许多灵活和动态的操作。在本文中,我们总结了OC中最实用的runtime特性,包括动态添加方法、动态交换方法、获取类的属性和方法列表、动态创建类和对象等,并通过实际代码示例演示了它们的用法。掌握了这些runtime特性,开发者可以更好地应对各种复杂的场景,提高开发效率,使代码更加灵活和强大。希望本文对读者有所帮助,让你在面试和工作中信心满满!