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(寫代碼)屬性。

如圖:


我們成功的給蒼老師添加個一個胸圍的屬性和一個寫代碼的回調,但是添加屬性沒有什麼意義,我們平時在開發過成功中用的比較多的就是添加回調了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章