为了保存状态信息,UIViewController需要持久化状态数据,持久化的方式与第18章介绍的归档(archiving)类似,也是使用NSCoder对象对数据进行编码(encoding)。下面就演示如何编码需要的状态数据。
打开BNRDetailViewController.m,编码当前BNRItem对象的itemKey属性,代码如下:
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
[coder encodeObject:self.item.itemKey
forKey:@“item.itemKey”];
[super encodeRestorableStateWithCoder:coder];
}
对应地,还需要实现解码(decoding)方法,通过itemKey在BNRItemStore中查找相应的BNRItem对象:
- (void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
NSString *itemKey =
[coder decodeObjectForKey:@“item.itemKey”];
for (BNRItem *item in [[BNRItemStore sharedStore] allItems]) {
if ([itemKey isEqualToString:item.itemKey]) {
self.item = item;
break;
}
}
[super decodeRestorableStateWithCoder:coder];
}
构建并运行应用,进入某一个BNRItem对象的详细界面,然后触发状态恢复。这次BNRDetailViewController可以正确显示之前选择的BNRItem。
现在还有一个问题:BNRDetailViewController在恢复状态时会将BNRItem的各项属性分别赋给对应的UITextField对象,如果用户之前在UITextField对象中输入过新值,那么这些新值就会丢失。为了解决该问题,需要在用户离开应用时将新值赋给BNRItem的对应属性,并保存修改后的BNRItem。由于encodeRestorableStateWithCoder:会在应用进入后台运行状态时调用,因此修改并保存BNRItem的代码同样可以写在该方法中。
在BNRDetailViewController.m中修改编码方法,代码如下:
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
[coder encodeObject:self.item.itemKey
forKey:@“item.itemKey”];
// 保存UITextField对象中的文本
self.item.itemName = self.nameField.text;
self.item.serialNumber = self.serialNumberField.text;
self.item.valueInDollars = [self.valueField.text intValue];
// 保存修改
[[BNRItemStore sharedStore] saveChanges];
[super encodeRestorableStateWithCoder:coder];
}
现在BNRDetailViewController可以很好地保存和恢复自身状态。下一节将为BNRItemsViewController添加状态恢复功能。