Objective C:通过自定义根类允许类别中的属性

时间:2013-12-16 15:00:54

标签: ios objective-c properties objective-c-category

关于类别属性问题有很多问题。 我知道解决这个问题的一些可能性:

从我的观点来看,两者都不干净,因为在创建此类属性的对象被解除分配时,永远不会清除分配的内存。

类别是保持代码清洁并向现有类动态添加功能的好方法。它们有助于将功能和分布式实现工作分组到更多开发人员中。

关于类别的坏处是缺少存储空间。

我现在多次遇到这个问题,我想知道以下是否会以一种干净的方式解决这个问题,同时也会关注内存,如果有任何我现在看不到的问题。< / p>

一个限制,我可以忽略,因为我是一名框架开发人员:我能够创建我的自己的根类类可以继承

首先声明新的根对象:

@interface RootObject : NSObject

- (void)setRuntimeProperty:(id)runtimeProperty forKey:(id<NSCopying>)key;
- (id)runtimePropertyForKey:(id)key;

@end

使用相应的实现:

#import "RootObject.h"

@interface RootObject ()
@property (readwrite) NSMutableDictionary *runtimeProperties;
@end

@implementation RootObject
@synthesize runtimeProperties = _runtimeProperties;

- (id)init {
    self = [super init];

    if (self)
    {
        _runtimeProperties = [[NSMutableDictionary alloc] initWithCapacity:1];
    }

    return self;
}

- (void)dealloc {
    [_runtimeProperties release];
    _runtimeProperties = nil;

    [super dealloc];
}

- (id)runtimePropertyForKey:(id)key {
    return [self.runtimeProperties objectForKey:key];
}

- (void)setRuntimeProperty:(id)runtimeProperty forKey:(id<NSCopying>)key {
    if (key)
    {
        if (runtimeProperty)
        {
            [self.runtimeProperties setObject:runtimeProperty forKey:key];
        }
        else
        {
            [self.runtimeProperties removeObjectForKey:key];
        }
    }
}

@end

使用此RootObject代替NSObject,将“属性”添加到类的类别应该非常容易。考虑使用一些课程MyClass

@interface MyClass : RootObject
// some interface here
@end

在此类上实现特殊行为时,您现在可以添加如下属性:

@interface MyClass (specialBehavior)
@property (nonatomic, retain) NSString *name;
@property (nonatomic, copy) NSDate *birthday;
@end

相应的实施:

@implementation MyClass (specialBehavior)
@dynamic name;
- (NSString *)name {
    return [self runtimePropertyForKey:@"name"];
}
- (void)setName:(NSString *)name {
    [self setRuntimeProperty:name forKey:@"name"];
}
@dynamic birthday;
- (NSDate *)birthday {
    return [self runtimePropertyForKey:@"birthday"];
}
- (void)setBirthday:(NSDate *)birthday {
    [self setRuntimeProperty:[birthday copy] forKey:@"birthday"];
}
@end

这样的实现也可以通过在setter方法中添加必要的调用来兼容KVO。 很直接,但我想知道我是否错过了重要的事情? (例如,具有许多此类声明属性或使用许多这些对象的非常非常糟糕的运行时性能)

1 个答案:

答案 0 :(得分:6)

这实际上与objc_setAssociatedObject和objc_getAssociatedObject相同,当取消分配对象时,执行释放内存(取决于关联类型)。我猜他们的开销也比建议的代码低得多。