iOS修改声明为readonly的值

首先定义一个测试用的类Test

Test.h

#import 

@interface Test : NSObject

@property (nonatomic, copy, readonly) NSString *testName;

@property (nonatomic, assign, readonly) NSInteger testAge;

- (instancetype)initWithTestName:(NSString *)name testAge:(NSInteger)age;

@end
Test.m

#import "Test.h"

@implementation Test

- (instancetype)initWithTestName:(NSString *)name testAge:(NSInteger)age{

    self = [super init];
    
    if (self) {
        
        _testName = name;
        _testAge = age;
    }
    return self;
}


@end

然后定义一个Test的类对象:

    Test *test = [[Test alloc] initWithTestName:@"testName" testAge:22];
    
    NSLog(@"%@",test.testName);

如果我们直接调用testName的setter方法,test.testName = @"修改了";会直接报错。提示这个属性是只读的。

报错信息

如果我们使用KVC呢?

    Test *test = [[Test alloc] initWithTestName:@"testName" testAge:22];
    
    NSLog(@"-%@",test.testName);
    
    [test setValue:@"修改了" forKey:@"testName"];
    
    NSLog(@"---%@",test.testName);

输出结果:

2017-05-17 14:20:36.404 iOS_readonlyTest[4076:115282] -testName
2017-05-17 14:20:36.404 iOS_readonlyTest[4076:115282] ---修改了

我们看到,使用****KVC****成功修改了声明为****readonly****的属性。

如果我们不想让 ****setValue:forKey:**** 方法改变对象的属性值,那么重写其类方法 ****+ (BOOL)accessInstanceVariablesDirectly**** 返回 NO (该方法默认返回 YES,即在不存在满足条件的存取方法时,允许直接访问属性对应的实例变量);在搜索实例变量时,会首先检查带下划线的实例变量,然后检查不带下划线的实例变量。

****提示:****

重写其类方法 ****+ (BOOL)accessInstanceVariablesDirectly**** 返回 NO的情况下,利用****KVC****修改声明为****readonly****的属性的值的时候会崩溃。我们可以重写类的****setValue:forKey:**** 方法,判断key是否是声明为****readonly****的属性,如果是直接返回。

- (void)setValue:(id)value forKey:(NSString *)key{
    
    if ([key isEqualToString:@"testName"]) {
        
        NSLog(@"这个属性不能被修改");
        return;
    }
    
    [super setValue:value forKey:key];
}
2017-05-17 14:29:35.894 iOS_readonlyTest[4108:118687] -testName
2017-05-17 14:29:35.894 iOS_readonlyTest[4108:118687] 这个属性不能被修改
2017-05-17 14:29:35.895 iOS_readonlyTest[4108:118687] ---testName

参考链接:http://www.jianshu.com/p/1ffa6414008e

你可能感兴趣的:(iOS修改声明为readonly的值)