Runtime方法的使用—Method、Ivar、Property篇

本篇主要是Method、Ivar、Property相關的方法調用


完整代碼在這裏

#pragma mark - IBAction
- (IBAction)logRunTimeAction:(id)sender {
    objc_property_attribute_t attrs[] = { { "T", "@\"NSString\"" }, { "&", "N" }, { "V", "" } };

    size_t objSize = class_getInstanceSize([_person class]);
    size_t allocSize = 2 * objSize;
    uintptr_t ptr = (uintptr_t)calloc(allocSize, 1);

    // Method
    Method method = [self class_getInstanceMethod:SelfClass selector:@selector(initial:)];
    [self method_getName:method];
    [self method_getImplementation:method]; // 該方法imp_implementationWithBlock使得imp幾乎相當於block
    [self method_getTypeEncoding:method];
    [self method_getArgumentType:method];
    [self method_copyReturnType:method];
    [self method_copyArgumentType:method];
    [self method_getReturnType:method];
    [self method_setImplementation:class_getInstanceMethod(SelfClass, @selector(method_setImplementation:))];
    [self method_exchangeImplementations:class_getInstanceMethod([_person class], @selector(runtimeTestAction3)) method:class_getInstanceMethod([_person class], @selector(runtimeTestAction2))];
    [self method_getDescription:method];
}

#pragma mark - Ivar get
/**
 *  獲取成員變量名
 *
 *  @param ivar 成員變量
 *
 *  @return 變量名
 */
- (const char *)ivar_getName:(Ivar)ivar {
    return ivar_getName(ivar);
}

/**
 *  獲取成員變量類型編碼
 *
 *  @param ivar 成員變量
 *
 *  @return 編碼類型
 */
- (const char *)ivar_getTypeEncoding:(Ivar)ivar {
    return ivar_getTypeEncoding(ivar);
}

/**
 *  獲取成員變量的偏移量
 *
 *  @param ivar 成員變量
 *
 *  @return 偏移量
 */
- (ptrdiff_t)ivar_getOffset:(Ivar)ivar {
    return ivar_getOffset(ivar);
}

#pragma mark - Property get
/**
 *  獲取屬性名
 *
 *  @param property 屬性
 *
 *  @return 屬性名
 */
- (const char *)property_getName:(objc_property_t)property {
    return property_getName(property);
}

/**
 *  獲取屬性特性描述字符串
 *
 *  @param property 屬性
 *
 *  @return 屬性特性字符串
 */
- (const char *)property_getAttributes:(objc_property_t)property {
    return property_getAttributes(property);
}

/**
 *  獲取屬性的特性列表
 *
 *  @param property 屬性
 *
 *  @return 特性列表
 */
- (objc_property_attribute_t *)property_copyAttributeList:(objc_property_t)property {
    unsigned int outCount;
    objc_property_attribute_t *objc_property_attributes = property_copyAttributeList(property,&outCount);
    for (int i = 0; i < outCount; i++) {
        objc_property_attribute_t objc_property_attribute = objc_property_attributes[i];
        NSLog(@"%s %s %s",__func__,objc_property_attribute.name,[self property_copyAttributeValue:property attributeName:objc_property_attribute.name]);
    }
    return objc_property_attributes;
}

/**
 *  獲取屬性中指定的特性
 *
 *  @param property      屬性
 *  @param attributeName 特性名
 *
 *  @return 特性
 */
- (const char *)property_copyAttributeValue:(objc_property_t)property attributeName:(const char *)attributeName {
    return property_copyAttributeValue(property,attributeName);
}

#pragma mark - Method invoke: 方法實現的返回值
/**
 *  調用指定方法的實現
 *
 *  @param receiver 被調用的對象
 *  @param method   被調用的方法
 */
- (void)method_invoke:(id)receiver method:(Method)method {
    method_invoke(receiver,method);
}

#pragma mark - Method get: 方法名;方法實現;參數與返回值相關
/**
 *  獲取方法名
 *
 *  @param method 方法
 *
 *  @return 方法選擇器
 */
- (SEL)method_getName:(Method)method {
    SEL sel = method_getName(method);
    NSLog(@"%s %@",__func__,NSStringFromSelector(sel));
    return sel;
}

/**
 *  返回方法的實現
 *
 *  @param method 方法
 *
 *  @return 方法的實現
 */
- (IMP)method_getImplementation:(Method)method {
    IMP imp = method_getImplementation(method);
    return imp;
}

/**
 *  獲取描述方法參數和返回值類型的字符串
 *
 *  @param method 方法
 *
 *  @return 方法的類型字符串
 */
- (const char *)method_getTypeEncoding:(Method)method {
    const char *methodType = method_getTypeEncoding(method);
    NSLog(@"%s %s",__func__,methodType);
    return methodType;
}

/**
 *  返回方法的參數的個數
 *
 *  @param method 方法
 *
 *  @return 方法參數的個數
 */
- (unsigned int)method_getNumberOfArguments:(Method)method {
    unsigned int num  = method_getNumberOfArguments(method);
    // 估計參數數量多出來的2個是調用的對象和selector
    NSLog(@"%s %@ has %d Arguments",__func__,NSStringFromSelector(method_getName(method)),num);
    return num;
}

#pragma mark - Method copy: 返回值類型,參數類型
/**
 *  獲取指定位置參數的類型字符串
 *
 *  @param method 方法
 */
- (void)method_getArgumentType:(Method)method {
    unsigned int argumentsCount = [self method_getNumberOfArguments:method];
    char argName[512] = {};
    for (unsigned int j = 0; j < argumentsCount; ++j) {
        method_getArgumentType(method, j, argName, 512);

        NSLog(@"%@ 第%u個參數類型爲:%s",NSStringFromSelector(method_getName(method)), j, argName);
        memset(argName, '\0', strlen(argName));
    }
}

/**
 *  獲取方法的指定位置參數的類型字符串
 *
 *  @param method 方法
 */
- (void)method_copyArgumentType:(Method)method {
    unsigned int argumentsCount = [self method_getNumberOfArguments:method];
    for (int i = 0; i < argumentsCount; i++) {
        NSLog(@"%s 第%d個 argument type %s",__func__,i,method_copyArgumentType(method,i));
    }
}

/**
 *  獲取方法的返回值類型的字符串
 *
 *  @param method 方法
 *
 *  @return 返回值類型字符串
 */
- (char *)method_copyReturnType:(Method)method {
    char *returnType = method_copyReturnType(method);
    NSLog(@"%s return type %s",__func__,returnType);
    return returnType;
}

/**
 *  通過引用返回方法的返回值類型字符串
 *
 *  @param method 方法
 */
- (void)method_getReturnType:(Method)method {
    char argNameType[512] = {};
    method_getReturnType(method,argNameType,512);
    NSLog(@"%s return type %s",__func__,argNameType);

}



#pragma mark - Method set: 方法實現 交換方法實現
/**
 *  設置方法的實現
 *
 *  @param method 方法
 */
- (void)method_setImplementation:(Method)method {
    IMP imp = imp_implementationWithBlock(^{
        NSLog(@"%s action",__func__);
    });
    method_setImplementation(method,imp);
}

/**
 *  交換兩個方法的實現
 *
 *  @param method1 方法1
 *  @param method2 方法2
 */
- (void)method_exchangeImplementations:(Method)method1 method:(Method)method2 {
    method_exchangeImplementations(method1,method2);
    [_person runtimeTestAction2];
    [_person runtimeTestAction3];
}


#pragma mark - Method 方法描述
- (struct objc_method_description *)method_getDescription:(Method)method {
    struct objc_method_description *description = method_getDescription(method);
    NSLog(@"%s %@",__func__,NSStringFromSelector(description->name));
    return description;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章