在NSOperation
中,executing
、finished
等属性都被声明为readonly
,但在继承NSOperation
的子类中,可能需要修改这些属性的值,该如何处理呢?
可在子类中添加如下的代码:
@synthesize executing = _executing;
@synthesize finished = _finished;
可参考:Overriding readonly property in subclass
转载自iOS修改声明为readonly的属性值
本文讨论的是,对于类中声明为 readonly
的属性值,我们就不可以修改其值了么?如何可以,那么如何修改呢?
为了便于说明,定义一个 ACLStudent
的类:
ACLStudent.h
@interface ACLStudent : NSObject
@property (nonatomic, assign, readonly) NSInteger studentId;
@property (nonatomic, copy, readonly) NSString *firstName;
@property (nonatomic, copy, readonly) NSString *lastName;
- (instancetype)initWithStudentId:(NSInteger)studentId firstName:(NSString *)firstName lastName:(NSString *)lastName;
@end
--------------------------
ACLStudent.m
@implementation ACLStudent
- (instancetype)initWithStudentId:(NSInteger)studentId firstName:(NSString *)firstName lastName:(NSString *)lastName {
self = [super init];
if (self) {
_studentId = studentId;
_firstName = [firstName copy];
_lastName = [lastName copy];
}
return self;
}
@end
接下来定义一个 ACLStudent
类的对象:
ACLStudent *student = [[ACLStudent alloc] initWithStudentId:1 firstName:@"Carya" lastName:@"Liu"];
NSLog(@"student firstName: %@", student.firstName);
现在我们考虑的就是如何修改 student
对象的 firstName
属性值为@"Qiu"
。
如果直接调用 firstName
的 setter
方法,student.firstName = @"Qiu"
, 那么就直接报错,提示不能够给声明为 readonly 的属性赋值。那么使用 KVC 呢?
[student setValue:@"Qiu" forKey:NSStringFromSelector(@selector(firstName))];
NSLog(@"student firstName after changed: %@", student.firstName);
运行,发现属性值被成功修改。哈哈,那么现在来看看 KVC 为什么能够修改该属性值呢?看看文档 Accessor Search Implementation Details。
当使用 setValue:forKey:
来设置对象的属性时,会以下面的优先顺序来寻找对应的 key:
set:
格式的存取方法。+ (BOOL)accessInstanceVariablesDirectly
返回 YES
,那么该对象会以 _
, _is
,
, is
的顺序查找是否存在对应的key。setValue:forUndefinedKey:
将会调用。setValue:forKey:
方法改变对象的属性值,那么重写其类方法 + (BOOL)accessInstanceVariablesDirectly
返回 NO
(该方法默认返回 YES
,即在不存在满足条件的存取方法时,允许直接访问属性对应的实例变量);在搜索实例变量时,会首先检查带下划线的实例变量,然后检查不带下划线的实例变量。对于上述第3点举例说明,如果修改 student
对象的属性 NSInteger studentId
, 注意其是 NSInteger
类型,我们在调用 setValue:forKey:
方法时可以像这样
[student setValue:@(20) forKey:NSStringFromSelector(@selector(studentId))];
传入一个 NSNumber 对象也可以,Objective-C 会处理好一切。
对于上面的示例,使用 setValue:forKey:
实际修改的是 student
实例中 _firstName
实例变量的值。不要忘记,我们在声明一个 firstName
的属性时,编译器会为我们自动合成一个 _firstName
的实例变量。
总结:
+ (BOOL)accessInstanceVariablesDirectly
重写,使其返回 NO.