两个问题:
如何只允许某个类更新属性?我尝试使用类别,但NotFriendly类仍然可以通过键值设置年龄属性。
为什么我得到" - [Person setAge:]:发送无法识别的选择器"我在运行时尝试使用age属性时出错了吗?
谢谢,
Person.h
@interface Person
@property (readonly) NSString *age;
@end
Person.m
@implementation Person
@synthesize age;
@end
人+ Exclusive.h
@interface Person
@property (readwrite) NSString *age;
@end
人+ Exclusive.h
@implementation Person (Exclusive)
@end
Friendly.m
#import "Person+Exclusive.h"
@interface Friendly
- (void)viewDidLoad {
[super viewDidLoad];
Person *aPerson = [[Person alloc] init];
aPerson.age = @"12"; // -[Person setAge:]: unrecognized selector sent to instance 0x174013e90
}
NotFriendly.m
#import "Person.h"
@interface Friendly
- (void)viewDidLoad {
[super viewDidLoad];
Person *aPerson = [[Person alloc] init];
[aPerson setValue:@"1000000" forKey:@"age"]; // how can I stop this
}
答案 0 :(得分:1)
你不可靠。添加到Objective-C类的任何方法对运行时中的每个人都是可见的;可用的方法是键值编码的工作原理。
如果它只是KVC你想要阻止那么你可以覆盖setValue:forKey:
并拒绝代理,如果名称密钥在你的黑名单上;否则请致电super
。但是类仍然可以performSelector:withObject:
甚至可以下降到C运行时,后者最终可以不做任何事情。
如果你处于Person
可以负责创建那些允许与之对话的对象的位置,那么它可以要求一个实例作为setter的参数,并且只有当该实例是一个你才能继续创建。将列表保存在您实例化的所有内容的弱集合中。
在任何检测到的失败案例中,无论采用何种方式,您都可以手动提升NSException
以创建所需的失败类型。
如果它只是用于调试构建而你不介意一堆麻烦,你可以调用[NSThread callStackSymbols]
并解析结果以找出正在调用的类的类型。返回的文本没有正式定义的格式,但直到现在才相当稳定;对于发布版本,它显然不可靠。但是,在调试版本中将其作为诊断工具保持工作不应该做太多工作。
答案 1 :(得分:0)
不确定为什么要这样做,但这是一个有趣的问题。
我想知道你是否可以创建一个带有两个参数的方法,即年龄和类。然后当你调用它时,你使用[self class]传入类。像这样:
- (void)checkTheClassBeforeSettingAge:(NSString *)age withClass:(NSClass *)class {
if (class isKindOfClass:[validClass class]) then {
self.age = age;
} else {
// Error handling code
}
}
用以下方式调用:
checkTheClassBeforeSettingAge:@"12" withClass:[self class];