一个简单的KVO例子。
两个界面,第一个界面显示名字和配偶(spouse)名字,第二个界面显示修改名字和配偶名字,返回时,将看到第一个界面的名字显示发生改变。
首先定义一个person类作为model。
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *address;
@property (strong, nonatomic) Person *spouse;
+ (instancetype)sharedPerson;
@end
#import "Person.h"
static Person *person = nil;
@implementation Person
+ (instancetype)sharedPerson
{
if (person == nil) {
person = [[Person alloc] init];
person.spouse = [[Person alloc] init];
}
return person;
}
@end
其次构建第一个界面,添加KVO。
#import "ViewController.h"
#import "Person.h"
#define KVO_CONTEXT_NAME_CHANGE @"kvoContextNameChange"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (weak, nonatomic) IBOutlet UILabel *spouseNameLabel;
@property (strong, nonatomic) Person *person;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.person = [Person sharedPerson];
[self _watchPersonForChangeName:self.person];
}
- (void)_watchPersonForChangeName:(Person *)person
{
[person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionInitial context:KVO_CONTEXT_NAME_CHANGE];
[person addObserver:self forKeyPath:@"spouse.name" options:NSKeyValueObservingOptionInitial context:KVO_CONTEXT_NAME_CHANGE];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == KVO_CONTEXT_NAME_CHANGE) {
self.nameLabel.text = [object valueForKey:@"name"];
self.spouseNameLabel.text = [object valueForKeyPath:@"spouse.name"];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)unwidSegue:(UIStoryboardSegue *)sender
{
}
@end
再次构建第二个界面,通过KVC方式修改名字。
#import "SecondViewController.h"
#import "Person.h"
@interface SecondViewController ()
@property (weak, nonatomic) IBOutlet UITextField *changeNameTextField;
@property (weak, nonatomic) IBOutlet UITextField *changeSpouseTextField;
@property (strong, nonatomic) Person *person;
- (IBAction)changeName:(id)sender;
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.person = [Person sharedPerson];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (IBAction)changeName:(id)sender {
NSString *name = self.changeNameTextField.text;
NSString *spouseName = self.changeSpouseTextField.text;
[self.person setValue:name forKey:@"name"];
[self.person setValue:spouseName forKeyPath:@"spouse.name"];
NSLog(@"spouse name: %@", self.person.spouse.name);
}
@end
说明,两个界面的.h文件里没有任何公共接口。界面用storyboard搭建。
这个例子非常简单。还需要对于下面方法进行深入研究:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context