Objective-C Runtime 1時間入門チュートリアル(中)


ソース: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

メールで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

メールで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(書き込みコード)のプロパティが追加されました.図:
私たちは蒼先生にバストの属性とコードを書くコールバックを追加することに成功しましたが、属性を追加することは意味がありません.私たちが普段開発した成功の中で使っているのはコールバックを追加することです.