在OC中,除了能够用setter和getter方法去操作对象中被保护的属性外,还可以同过键值编码的方式去访问,也就是KVC。
说白了,也就是调用如下几个方法去操作属性:
- (void)setValue:(id)value forKey:(NSString *)key;
- (id)valueForKey:(NSString *)key;
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (id)valueForKeyPath:(NSString *)keyPath;
那么如何使用KVC去操作属性呢?我们用一个实例去讲解:
一:以下两个方法的操作:
- (void)setValue:(id)value forKey:(NSString *)key;
- (id)valueForKey:(NSString *)key;
1.创建一个Student类,代码如下:
Student.h 文件代码如下:
#import <Foundation/Foundation.h>
@interface Student : NSObject {
NSString *_name;
}
- (void)setName:(NSString *)name;
- (NSString *)name;
@end
Student.m 文件代码如下:
#import "Student.h"
@implementation Student
- (void)setName:(NSString *)name {
NSLog(@"调用了:%s",__FUNCTION__);
_name = name;
}
- (NSString *)name {
NSLog(@"调用了:%s",__FUNCTION__);
return _name;
}
@end
main.m 文件代码如下:
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] init];
[stu setValue:@"张三" forKey:@"name"];
NSLog(@"student.name = %@",[stu valueForKey:@"name"]);
NSLog(@"------------万恶的分割线------------");
[stu setValue:@"李四" forKey:@"_name"];
NSLog(@"student.name = %@",[stu valueForKey:@"name"]);
}
return 0;
}
测试结果如下:
2015-08-08 01:59:31.292 Demo[1082:75782] 调用了:-[Student setName:]
2015-08-08 01:59:31.332 Demo[1082:75782] 调用了:-[Student name]
2015-08-08 01:59:31.333 Demo[1082:75782] student.name = 张三
2015-08-08 01:59:31.333 Demo[1082:75782] ------------万恶的分割线------------
2015-08-08 01:59:31.334 Demo[1082:75782] 调用了:-[Student name]
2015-08-08 01:59:31.334 Demo[1082:75782] student.name = 李四
结论:
(1).@“name”操作属性时,会自动查找--(void)setName:(NSString *)name/--(NSString *)name方法,若没有找到该方法,则继续查找student中的name属性,如果也没有找到name属性,则查找_name属性,还没有找到,则报错!
(2)._name操作属性时,自动操作Student中的_name属性,若没有找到,则报错。
二:以下两个方法的操作:
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (id)valueForKeyPath:(NSString *)keyPath;
1.定义两个类:Student类和Book类
Book.h 的文件代码如下:
#import <Foundation/Foundation.h>
@interface Book : NSObject
@property (nonatomic,copy) NSString *bookName;
@end
Book.m 的代码文件如下:
#import "Book.h"
@implementation Book
@end
Student.h 的代码文件如下:
#import <Foundation/Foundation.h>
@class Book;
@interface Student : NSObject
@property (nonatomic,strong) Book *book;
@end
Student.m 的代码文件如下:
#import "Student.h"
@implementation Student
@end
main.m 的代码文件如下:
#import <Foundation/Foundation.h>
#import "Student.h"
#import "Book.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] init];
Book *book = [[Book alloc] init];
[stu setValue:book forKey:@"_book"];
[stu setValue:@"红楼梦" forKeyPath:@"_book._bookName"];
NSLog(@"book.bookName = %@",[stu valueForKeyPath:@"_book._bookName"]);
}
return 0;
}
测试结果如下:
2015-08-08 02:24:01.579 Demo[1111:79395] book.bookName = 红楼梦
注意:使用KVC会破坏面向对象中的封装性,所以要谨慎使用!