KVC 键值编码
全称是Key-value coding,翻译成键值编码。它提供了一种使用字符串而不是访问器方法去访问一个对象实例变量的机制。
1.通过key(成员变量的名称)设置value(成员变量的值)
- (void)setValue:(id)value forKey:(NSString *)key;
2.通过keyPath(成员变量的路径)设置value(成员变量的值)
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
3.通过key(成员变量的名称)获取value(成员变量的值)
- (id)valueForKey:(NSString *)key;
4.通过keyPath(成员变量的路径)获取value(成员变量的值)
- (id)valueForKeyPath:(NSString *)keyPath;
5.重写此方法防止出现未定义key值的时候出现崩溃
- (void)setValue:(id)value forUndefinedKey:(NSString *)key;
6.重写此方法防止获取未定义key值的时候出现崩溃
- (id)valueForUndefinedKey:(NSString *)key;
7.通过键值对的形式给成员变量赋值
- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;
举个简单的例子:一个对象拥有某些属性。比如说,一个 Person 对象有一个 perName,uid,perID和一个 sex 属性。以 KVC 说法,Person 对象分别有一个 value 对应他的 perName,uid,perID和一个 sex 的 key。 key 只是一个字符串,它对应的值可以是任意类型的对象。从最基础的层次上看,KVC 有两个方法:一个是设置 key 的值,另一个是获取 key 的值。
#import @interface Person : NSObject@property (nonatomic,copy)NSString *perName;
@property (nonatomic,copy)NSString *sex;
@property (nonatomic,copy)NSString *uid;
@property (nonatomic,copy)NSString *perID;@end
#import "Person.h"@implementation Person-(void)setValue:(id)value forKey:(NSString *)key{//判断是否为NSNumber类型if ([value isKindOfClass:[NSNumber class]]) {[self setValue:[NSString stringWithFormat:@"%@",value] forKey:key];}else {//调用父类的方法[super setValue:value forKey:key];}}-(void)setValue:(id)value forUndefinedKey:(NSString *)key{//手动赋值if ([key isEqualToString:@"id"]) {[self setValue:value forKey:@"perID"];}else{NSLog(@"未定的key值:%@",key);}}-(id)valueForUndefinedKey:(NSString *)key{NSLog(@"未找到key:%@",key);return nil;
}- (NSString *)description
{return [NSString stringWithFormat:@"name = %@,sex = %@,ID= %@,perID = %@", _perName,_sex,_uid,_perID];
}@end
#import
#import "Person.h"int main(int argc, const char * argv[]) {@autoreleasepool {Person *per = [Person new];//模拟返回的服务器数据NSDictionary *dictionary = @{@"perName":@"小红",@"sex":@"女",@"uid":[NSNumber numberWithInteger:888],@"id":@"12345"};//通过KVC一次性给3个成变量赋值[per setValuesForKeysWithDictionary:dictionary];NSLog(@" %@",per);}return 0;
}
========================================
KVO 键值观察者模式
全称是Key-value observing,翻译成键值观察。提供了一种当其它对象属性被修改的时候能通知当前对象的机制
1.添加观察者
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
2.对象被释放之前,要移除观察者,通常写在dealloc函数当中
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
3.当属性值发生变化之后的回调函数
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
监听一个contentSize的例子:点击一个加号会添加10个cell
#import "ViewController.h"@interface ViewController ()@property (nonatomic,assign)NSInteger count;//控制行数
@property (nonatomic,assign)CGSize recordSize;//记录当前UITableView的ContentSize;
@property (weak, nonatomic) IBOutlet UITableView *myTableView;@end@implementation ViewController-(void)dealloc{//移除观察者[self.myTableView removeObserver:self forKeyPath:@"contentSize"];}- (void)viewDidLoad {[super viewDidLoad];//观察myTableView的contentSize[self.myTableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];//设置导航栏右侧按钮self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"+" style:UIBarButtonItemStylePlain target:self action:@selector(add)];self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"__" style:UIBarButtonItemStylePlain target:self action:nil];}//增加行数
-(void)add{self.count += 10;//刷新UI[self.myTableView reloadData];//self.recordSize = self.myTableView.contentSize;//NSLog(@"%f",self.recordSize.height);
}
#pragma mark- KVO回调方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{//判断是否为对应的观者属性if ([keyPath isEqualToString:@"contentSize"] && object == self.myTableView) {NSLog(@"%@ %f",change, self.recordSize.height);//记录变化之后的contentSizeself.recordSize = [change[@"new"] CGSizeValue];}}#pragma mark- UITableView代理
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{return self.count;
}-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{return 1;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];if (!cell) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];}cell.textLabel.text = @"哈哈";return cell;}@end
如果对你有帮助,请关注我哦!