objc 的 ivar 和 associated object

用 associated object 的方式加变量,并不会改变 ivar list

Associated Objects - NSHipster

class_copyIvarList方法获取实例变量问题引发的思考 - zhanggui - 博客园

//
//  main.m
//

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

#import <objc/runtime.h>

@interface TestClass : NSObject
{
    int x;
    int y;
    int z;
}
@property int x;
@property int y;
@property int z;
@end

@implementation TestClass
@synthesize x, y, z;
@end

@interface TestClass (MyCategory)
@property(nonatomic, assign) id w;
@end

@implementation TestClass (MyCategory)

- (id)w {
    return objc_getAssociatedObject(self, @selector(w));
}
- (void)setW:(id)w {
    objc_setAssociatedObject(self, @selector(w), w, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

static NSArray *ClassMethodNames(Class c)
{
    NSMutableArray *array = [NSMutableArray array];

    unsigned int methodCount = 0;
    Method *methodList = class_copyMethodList(c, &methodCount);
    unsigned int i;
    for(i = 0; i < methodCount; i++)
        [array addObject: NSStringFromSelector(method_getName(methodList[i]))];
    free(methodList);

    return array;
}

static void PrintDescription(NSString *name, id obj)
{
    // id s = obj->isa;
    // id s = [obj class]; // 与下面的答案不同,如果 obj 被 KVO 的话
    id s = object_getClass(obj); 
    NSString *str = [NSString stringWithFormat:
                     @"%@: %@\n\tNSObject class %s\n\tlibobjc class %s\n\timplements methods <%@>",
                     name,
                     obj,
                     class_getName([obj class]),
                     class_getName(s),
                     [ClassMethodNames(s) componentsJoinedByString:@", "]];
    printf("%s\n", [str UTF8String]);
}




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

    TestClass *x = [[TestClass alloc] init];
    TestClass *y = [[TestClass alloc] init];
    TestClass *xy = [[TestClass alloc] init];
    TestClass *control = [[TestClass alloc] init];

    [x addObserver:x forKeyPath:@"x" options:0 context:NULL];
    [xy addObserver:xy forKeyPath:@"x" options:0 context:NULL];
    [y addObserver:y forKeyPath:@"y" options:0 context:NULL];
    [xy addObserver:xy forKeyPath:@"y" options:0 context:NULL];

    PrintDescription(@"control", control);
    PrintDescription(@"x", x);
    PrintDescription(@"y", y);
    PrintDescription(@"xy", xy);

    unsigned int count = 0;
    Ivar *ivars = class_copyIvarList(TestClass.self, &count);
    NSMutableString *ivarNames = NSMutableString.new;
    for (NSInteger i = 0; i < count; ++i) { // count 为 3,也就是 w 并没被计入
        [ivarNames appendFormat:@"%s, ", ivar_getName(ivars[i])];
    }
    free(ivars);
    NSLog(@"TestClass's associated property: (%u) %@", count, ivarNames);

    printf("Using NSObject methods, normal setX: is %p, overridden setX: is %p\n",
           [control methodForSelector:@selector(setX:)],
           [x methodForSelector:@selector(setX:)]);
    printf("Using libobjc functions, normal setX: is %p, overridden setX: is %p\n",
           method_getImplementation(class_getInstanceMethod(object_getClass(control),
                                                            @selector(setX:))),
           method_getImplementation(class_getInstanceMethod(object_getClass(x),
                                                            @selector(setX:))));

    NSString * appDelegateClassName;
    @autoreleasepool {
        // Setup code that might create autoreleased objects goes here.
        appDelegateClassName = NSStringFromClass([AppDelegate class]);
    }
    return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值