如何授予某些类来在Objective-C中设置我的属性?

时间:2015-06-25 02:40:21

标签: objective-c

两个问题:

  1. 如何只允许某个类更新属性?我尝试使用类别,但NotFriendly类仍然可以通过键值设置年龄属性。

  2. 为什么我得到" - [Person setAge:]:发送无法识别的选择器"我在运行时尝试使用age属性时出错了吗?

  3. 谢谢,

    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
    }
    

2 个答案:

答案 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];