readonly属性值的修改方案讨论
来源:互联网 发布:扬州网络电视台app 编辑:程序博客网 时间:2024/05/21 09:59
问题
前两天面试,被问到关键词readonly修饰的属性访问操作,如何实现只读属性的修改?
比如:在某些SDK中,没有提供相应接口,但实际项目中却要求要有对某些属性的修改权限,这时可能就要考虑如何修改只读属性了。
再比如:UITableView的只读属性style(UITableViewStylePlain/UITableViewStyleGrouped)
// LGYStudent.h// 对外提供只读属性firstName@interface LGYStudent : NSObject@property (nonatomic, assign, readonly) NSInteger studentId;@property (nonatomic, copy, readonly) NSString *firstName;@property (nonatomic, copy) NSString *lastName;- (instancetype)initWithStudentId:(NSInteger)studentId firstName:(NSString *)firstName lastName:(NSString *)lastName;@end
解决方案
- 方法一: KVC setValue:forKey:
LGYStudent *student = [[LGYStudent alloc] initWithStudentId:1 firstName:@"yang" lastName:@"Liu"]; NSLog(@"student firstName: %@", student.firstName); // student firstName: yang [student setValue:@"KVC" forKey:NSStringFromSelector(@selector(firstName))]; NSLog(@"student firstName after changed-KVC: %@", student.firstName); // student firstName after changed-KVC: KVC
参考:http://www.jianshu.com/p/1ffa6414008e
Apple文档相关链接:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueCoding/Compliant.html
- 方法二: setValue:forKeyPath:
[student setValue:@"KeyPath" forKeyPath:@"firstName"]; NSLog(@"student firstName after changed-KeyPath: %@", student.firstName); // student firstName after changed-KVC: KeyPath
- 方法三: category + runtime 重写get/set方法
在分类中通过runtime重新设置属性的set、get方法时,需要在对象初始化对该属性赋值之后,单独再对该属性作一下赋值操作。
因为分类里的重写方法要先于并取代 本类里的原方法执行。
而且在本类的初始化构造器方法里对属性赋值多是以实例变量的下划线形式(_associatedObject)赋值,不通过set方法。
// LGYStudent+RunTime.h#import "LGYStudent.h"@interface LGYStudent (RunTime)- (NSString *)firstName;- (void)setFirstName:(NSString *)firstName;@end
// LGYStudent+RunTime.m#import "LGYStudent+RunTime.h"#import <objc/runtime.h>@implementation LGYStudent (RunTime)static char kFirstName;- (NSString *)firstName { return objc_getAssociatedObject(self, &kFirstName);}-(void)setFirstName:(NSString *)firstName { objc_setAssociatedObject(self, &kFirstName, firstName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);}@end
修改该对象的只读属性时
student.firstName = @"RunTime"; NSLog(@"student firstName after changed-RunTime: %@", _student.firstName); // student firstName after changed-RunTime: RunTime
总结
- 当我们声明一个 readonly 的属性,外部可能会通过 KVC 修改该属性值。
- 为了避免 KVC 修改属性值,须将定义属性所在类的类方法 + (BOOL)accessInstanceVariablesDirectly 重写,使其返回 NO.
- 请注意:如果使用上面第三种方法runtime重写set/get方法,则 + (BOOL)accessInstanceVariablesDirectly方法是不执行的。
- 因为如上所述KVC原理的执行顺序,此时已经找到set方法了,就不会再执行这个类方法了。返回YES/NO都不再起作用了。
如果是自己封装SDK的话,在.h 文件设计中,对外属性p的设计是readonly时,外界便不能修改该属性。
那么想要在该类内部要修改该p属性,有两种方式
- 可以通过指针访问
_studentId = studentId; self->_firstName = [firstName copy];
- 也可以在类的拓展里重新声明属性为可读属性
@interface LGYStudent ()@property (nonatomic, copy) NSString *firstName;@end
参考:http://blog.csdn.net/skymingst/article/details/42026695
或者用协议protocol的方式,外部通过protocol获取属性,这样也可以达到隐藏成员变量的效果。比如UITableView的numberOfSections,indexPathForSelectedRow等只读属性,就是通过协议方法设置的。
附上示例代码链接 https://pan.baidu.com/s/1hsmkOfE
- readonly属性值的修改方案讨论
- iOS修改声明为readonly的属性值
- asp.net textbox的readonly属性设置方案
- readOnly属性 (不可修改)
- TextBox的ReadOnly属性
- Checkbox的 readonly 属性
- extjs datefield的readOnly属性
- Input的readonly 属性与disabled属性
- C#属性的讨论
- readonly属性
- JSF中输入组件的readonly属性
- javascript 控制 text 的 readonly 属性
- 小心使用 asp:TextBox 的ReadOnly属性
- input属性disabled和readonly的区别
- 关于TextBox的Enable与ReadOnly属性
- 关于TextBox的Enable与ReadOnly属性
- TextBox的Enable与ReadOnly属性
- HTML <input> 标签的 readonly 属性
- Java并发编程:并发容器之CopyOnWriteArrayList(转载)
- php的phpMyAdmin数据库怎么装上使用
- 动态规划练习--03(采药)
- 那些奇奇怪怪的语句
- IDEA Springboot Tomcat热部署
- readonly属性值的修改方案讨论
- Ansible配置支持Windows(远程节点)流程
- 等价二叉树样例 1 1 / \ / \ 2 2 and 2 2 / / 4
- 【MySQL基础】数据的增删改查
- Unity简单UI框架搭建
- Android中的PendingIntent
- 服务器远程安装Matlab2015
- [2017雅礼集训]day10 T2 数列 最长上升子序列
- TLD运动检测与目标跟踪详细介绍