Objective-C Runtime 一小时入门教程(中)

来源:ian(@ianisme)
链接:http://www.ianisme.com/ios/2019.html

获取类的成员变量和属性篇

苍老师在大家心目中应该有很多特征吧,下面我们通过代码来获取苍老师的特征。

People.h文件

@interface People : NSObject
{
    NSString *_occupation;
    NSString *_nationality;
}

@property (nonatomic, copy) NSString *name;
@property (nonatomic) NSUInteger age;

- (NSDictionary *)allProperties;
- (NSDictionary *)allIvars;
- (NSDictionary *)allMethods;
 @end

People.m文件

#if TARGET_IPHONE_SIMULATOR
#import <objc/objc-runtime.h>
#else
#import <objc/runtime.h>
#import <objc/message.h>
#endif

@implementation People

- (NSDictionary *)allProperties
{
    unsigned int count = 0;

    // 获取类的所有属性,如果没有属性count就为0
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    NSMutableDictionary *resultDict = [<a href="http://www.jobbole.com/members/www821839432">@{}</a> mutableCopy];

    for (NSUInteger i = 0; i < count; i ++) {

        // 获取属性的名称和值
        const char *propertyName = property_getName(properties[i]);
        NSString *name = [NSString stringWithUTF8String:propertyName];
        id propertyValue = [self valueForKey:name];

        if (propertyValue) {
            resultDict[name] = propertyValue;
        } else {
            resultDict[name] = @"字典的key对应的value不能为nil哦!";
        }
    }

    // 这里properties是一个数组指针,我们需要使用free函数来释放内存。
    free(properties);

    return resultDict;
}

- (NSDictionary *)allIvars
{
    unsigned int count = 0;

    NSMutableDictionary *resultDict = [<a href="http://www.jobbole.com/members/www821839432">@{}</a> mutableCopy];

    Ivar *ivars = class_copyIvarList([self class], &count);

    for (NSUInteger i = 0; i < count; i ++) {

        const char *varName = ivar_getName(ivars[i]);
        NSString *name = [NSString stringWithUTF8String:varName];
        id varValue = [self valueForKey:name];

        if (varValue) {
            resultDict[name] = varValue;
        } else {
            resultDict[name] = @"字典的key对应的value不能为nil哦!";
        }

    }

    free(ivars);

    return resultDict;
}

- (NSDictionary *)allMethods
{
    unsigned int count = 0;

    NSMutableDictionary *resultDict = [<a href="http://www.jobbole.com/members/www821839432">@{}</a> mutableCopy];

    // 获取类的所有方法,如果没有方法count就为0
    Method *methods = class_copyMethodList([self class], &count);

    for (NSUInteger i = 0; i < count; i ++) {

        // 获取方法名称
        SEL methodSEL = method_getName(methods[i]);
        const char *methodName = sel_getName(methodSEL);
        NSString *name = [NSString stringWithUTF8String:methodName];

        // 获取方法的参数列表
        int arguments = method_getNumberOfArguments(methods[i]);

        resultDict[name] = @(arguments-2);
    }

    free(methods);

    return resultDict;
}

@end

在main.m中运行以下代码

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        People *cangTeacher = [[People alloc] init];
        cangTeacher.name = @"苍井空";
        cangTeacher.age = 18;
        [cangTeacher setValue:@"老师" forKey:@"occupation"];

        NSDictionary *propertyResultDic = [cangTeacher allProperties];
        for (NSString *propertyName in propertyResultDic.allKeys) {
            NSLog(@"propertyName:%@, propertyValue:%@",propertyName, propertyResultDic[propertyName]);
        }

        NSDictionary *ivarResultDic = [cangTeacher allIvars];
        for (NSString *ivarName in ivarResultDic.allKeys) {
            NSLog(@"ivarName:%@, ivarValue:%@",ivarName, ivarResultDic[ivarName]);
        }

        NSDictionary *methodResultDic = [cangTeacher allMethods];
        for (NSString *methodName in methodResultDic.allKeys) {
            NSLog(@"methodName:%@, argumentsCount:%@", methodName, methodResultDic[methodName]);
        }

    }
    return 0;
}

最后的输出结果如下:
Objective-C Runtime 一小时入门教程(中)_第1张图片

是不是有点失望,我没有加一些特殊的技能,留给下文了。此实战内容是通过苍老师的一些特征学习:如何获取对象所有的属性名称和属性值、获取对象所有成员变量名称和变量值、获取对象所有的方法名和方法参数数量。

6.3 苍老师增加新技能篇

苍老师要通过Category和Associated Objects增加技能了,快看!
创建People+Associated.h文件如下:

#import "People.h"

typedef void (^CodingCallBack)();

@interface People (Associated)

@property (nonatomic, strong) NSNumber *associatedBust; // 胸围
@property (nonatomic, copy) CodingCallBack associatedCallBack;  // 写代码

@end

People+Associated.m如下:

#import "People+Associated.h"
#if TARGET_IPHONE_SIMULATOR
#import <objc/objc-runtime.h>
#else
#import <objc/runtime.h>
#import <objc/message.h>
#endif
@implementation People (Associated)
- (void)setAssociatedBust:(NSNumber *)bust
{
    // 设置关联对象
    objc_setAssociatedObject(self, @selector(associatedBust), bust, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSNumber *)associatedBust
{
    // 得到关联对象
    return objc_getAssociatedObject(self, @selector(associatedBust));
}
- (void)setAssociatedCallBack:(CodingCallBack)callback {
    objc_setAssociatedObject(self, @selector(associatedCallBack), callback, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (CodingCallBack)associatedCallBack {
    return objc_getAssociatedObject(self, @selector(associatedCallBack));
}

@end

在main.m中运行以下代码

#import "People.h"
#import "People+Associated.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        People *cangTeacher = [[People alloc] init];
        cangTeacher.name = @"苍井空";
        cangTeacher.age = 18;
        [cangTeacher setValue:@"老师" forKey:@"occupation"];
        cangTeacher.associatedBust = @(90);
        cangTeacher.associatedCallBack = ^(){

            NSLog(@"苍老师要写代码了!");

        };
        cangTeacher.associatedCallBack();

        NSDictionary *propertyResultDic = [cangTeacher allProperties];
        for (NSString *propertyName in propertyResultDic.allKeys) {
            NSLog(@"propertyName:%@, propertyValue:%@",propertyName, propertyResultDic[propertyName]);
        }
        NSDictionary *methodResultDic = [cangTeacher allMethods];
        for (NSString *methodName in methodResultDic.allKeys) {
            NSLog(@"methodName:%@, argumentsCount:%@", methodName, methodResultDic[methodName]);
        }
    }
    return 0;
}

这次运行结果多出了一个associatedBust(胸围)和一个associatedCallBack(写代码)属性。
如图:

我们成功的给苍老师添加个一个胸围的属性和一个写代码的回调,但是添加属性没有什么意义,我们平时在开发过成功中用的比较多的就是添加回调了。

你可能感兴趣的:(Objective-C,Class)