KVC 和 KVO
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 <Foundation/Foundation.h>@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 <Foundation/Foundation.h>
#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 ()<UITableViewDataSource,UITableViewDelegate>@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
?如果對你有幫助,請關注我哦!
轉載于:https://www.cnblogs.com/laolitou-ping/p/6256486.html
總結