美文网首页实用轮子iOS 开发
iOS runtime运行时基本功能

iOS runtime运行时基本功能

作者: 西蒙SIMON | 来源:发表于2016-06-21 00:22 被阅读60次
一个模型类PCBitch

PCBitch.h

#import <Foundation/Foundation.h>

@interface PCBitch : NSObject

@property(nonatomic, copy, readonly) NSString *name;
- (void)sayHello;
@end

PCBitch.m

#import "PCBitch.h"

@interface PCBitch()

@property(nonatomic, assign) int age;
@property(nonatomic, assign) int height;
@property(nonatomic, copy) NSString *cupSize;

@end

@implementation PCBitch

- (instancetype)init {
    if (self = [super init]) {
        _name = @"Batrick";
        _age = 21;
        _height = 168;
        _cupSize = @"C";
    }
    
    return self;
}

- (void)sayHello {
    NSLog(@"Hello, I'm %@", _name);
}

- (void)sayHoney {
    NSLog(@"Ai yo, honey~");
}

+ (void)papapa {
    NSLog(@"papapapa");
}

@end

模型分类PCBitch+Asshole,动态添加“属性”

PCBitch+Asshole.h

#import "PCBitch.h"

@interface PCBitch (Asshole)

@property(nonatomic, copy) NSString *assholeName;

@end

PCBitch+Asshole.m

#import "PCBitch+Asshole.h"
#import <objc/runtime.h>

static char assholeNameChar;

@implementation PCBitch (Asshole)

- (void)setAssholeName:(NSString *)assholeName {
    objc_setAssociatedObject(self, &assholeNameChar, assholeName, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (NSString *)assholeName {
    return objc_getAssociatedObject(self, &assholeNameChar);
}

@end

展示类PCBitchShowStage

#import "PCBitchShowStage.h"
#import "PCBitch.h"
#import "PCBitch+Asshole.h"
#import <objc/runtime.h>

@implementation PCBitchShowStage

void sayAhName(id self, SEL _cmd);

+ (void)show {
    PCBitch *pBitch = [[PCBitch alloc] init];
    [pBitch setValue:@"Zhangsan" forKey:@"_name"];
    [pBitch sayHello];
    
    // 添加属性
    pBitch.assholeName = @"pppppp";
    NSLog(@"The assholeName of the bitch: %@", pBitch.assholeName);
    
    
//    // 利用runtime读取类属性
    unsigned int propertyCount;
    objc_property_t *propertyList = class_copyPropertyList([pBitch class], &propertyCount);
    NSLog(@"property count: %zd", propertyCount);
    for (int i=0; i<propertyCount; i++) {
        objc_property_t property = propertyList[i];
        NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
        
        char returntype[512] = {};
        method_getReturnType(class_getInstanceMethod([pBitch class], NSSelectorFromString(propertyName)), returntype, 512);
        
        NSString *returnTypeStr = [NSString stringWithUTF8String:returntype];
//        NSLog(@"property:%@, return type: %@", propertyName, returnTypeStr);
        NSString *outputType = nil;
        if ([returnTypeStr isEqualToString:@"i"]) {
            outputType = @"%d";
            
        } else if ([returnTypeStr isEqualToString:@"d"]) {
            outputType = @"%f";
            
        } else {
            outputType = @"%@";
        }
        
        NSString *preStr = [NSString stringWithFormat:@"property name:%%@, value: %@", outputType];
        NSLog(preStr, propertyName, [pBitch performSelector:NSSelectorFromString(propertyName)]);
    }

    // 获取所有实例方法
    unsigned int methodCount;
    Method *methodList = class_copyMethodList([pBitch class], &methodCount);
    for (int i=0; i<methodCount; i++) {
        Method method = methodList[i];
        NSLog(@"method name: %@, encoding type: %@", NSStringFromSelector(method_getName(method)), [NSString stringWithUTF8String:method_getTypeEncoding(method)]);
    }

    // 获取所有类方法
    unsigned int methodCount2;
    Class metaClass = objc_getMetaClass(class_getName([pBitch class]));
    Method *methodList2 = class_copyMethodList(metaClass, &methodCount2);
    for (int i=0; i<methodCount2; i++) {
        Method method = methodList2[i];
        NSLog(@"class method name: %@, encoding type: %@", NSStringFromSelector(method_getName(method)), [NSString stringWithUTF8String:method_getTypeEncoding(method)]);
    }

    // 动态添加一个实例方法
//        [pBitch sayAh]; // compile error
    if ([pBitch respondsToSelector:@selector(sayAh)]) {
        [pBitch performSelector:@selector(sayAh)];
    } else {
        NSLog(@"The bitch doesn't say Ah!");
    }

    NSLog(@"After teaching...");
    class_addMethod([pBitch class], @selector(sayAh), (IMP)sayAhName, "v@:");

    if ([pBitch respondsToSelector:@selector(sayAh)]) {
        [pBitch performSelector:@selector(sayAh)];
    }

    // 替换方法实现
    [pBitch sayHello];
    IMP imp = class_getMethodImplementation(self, @selector(sayFuckMeImp));
    class_replaceMethod([pBitch class], @selector(sayHello), (IMP)imp, method_getTypeEncoding(class_getInstanceMethod([pBitch class], @selector(sayHello))));
    [pBitch sayHello];
    
    
    // 动态创建一个类
    Class GodnessClass = objc_allocateClassPair([NSObject class], "PCGodness", 0);
    class_addMethod(GodnessClass, @selector(bless), class_getMethodImplementation(self, @selector(blessImp)), "v@:");
    objc_registerClassPair(GodnessClass);
    id godness = [[GodnessClass alloc] init];
    [godness performSelector:@selector(bless)];
}

void sayAhName(id self, SEL _cmd) {
    PCBitch *b = (PCBitch *)self;
    NSLog(@"Ah~, call me %@ baby~", b.name);
}

- (void)sayFuckMeImp {
    NSLog(@"Come on, fuck me baby!");
}

- (void)blessImp {
    NSLog(@"Godness bless you, kid.");
}

@end

相关文章

网友评论

    本文标题:iOS runtime运行时基本功能

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