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

6.2 苍老师的特征篇


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

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">@{}</amutableCopy];

 

    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">@{}</amutableCopy];

 

    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">@{}</amutableCopy];

 

    // 获取类的所有方法,如果没有方法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;

}


最后的输出结果如下:



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


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(写代码)属性。

如图:


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值