首页 » iOS编程(第4版) » iOS编程(第4版)全文在线阅读

《iOS编程(第4版)》11.5 创建并使用键

关灯直达底部

将照片加入BNRImageStore对象时,需要针对不同的照片使用不同的键,然后将这个键赋给相应的BNRItem对象。当BNRDetailViewController对象要从BNRImageStore对象载入照片时,需要先从BNRItem对象得到照片的键,然后通过BNRImageStore对象查找相应的照片。在BNRItem.h中为BNRItem类添加itemKey属性,用来保存照片的键,代码如下:

@property (nonatomic, readonly, strong) NSDate *dateCreated;

@property (nonatomic, copy) NSString *itemKey;

照片的键不能重复,否则无法通过BNRImageStore对象中的字典对象准确地保存对象。有很多种途径可以生成无重复的字符串(unique string),本节将使用Cocoa Touch提供的一种机制,这种机制可以生成唯一标识(UUID,也称为GUID)。每一个NSUUID类的对象都表示一个唯一的UUID。UUID是基于当前时间、计数器(counter)和硬件标识(通常为无线网卡的MAC地址)等数据计算生成的。如果使用字符串表示UUID,则示例如下:

4A73B5D2-A6F4-4B40-9F82-EA1E34C1DC04

在BNRDetailViewController.m顶部导入BNRImageStore.h,代码如下:

#import “BNRDetailViewController.h”

#import “BNRItem.h”

#import “BNRImageStore.h”

打开BNRItem.m,修改指定初始化方法,生成一个UUID并设置为itemKey:

- (instancetype)initWithItemName:(NSString *)name

valueInDollars:(int)value

serialNumber:(NSString *)sNumber

{

// 调用父类的指定初始化方法

self = [super init];

// 父类的指定初始化方法是否成功创建了父类对象?

if (self) {

// 为对象变量设定初始值

_itemName = name;

_serialNumber = sNumber;

_valueInDollars = value;

// 设置_dateCreated的值为系统当前时间

_dateCreated = [[NSDate alloc] init];

// 创建一个NSUUID对象,然后获取其NSString类型的值

NSUUID *uuid = [[NSUUID alloc] init];

NSString *key = [uuid UUIDString];

_itemKey = key;

}

// 返回初始化后的对象的新地址

return self;

}

然后修改BNRDetailViewController.m中的imagePickerController:didFinish- PickingMediaWithInfo:,将UIImage对象存入BNRImageStore对象:

- (void)imagePickerController:(UIImagePickerController *)picker

didFinishPickingMediaWithInfo:(NSDictionary *)info

{

UIImage *image = info[UIImagePickerControllerOriginalImage];

// 以itemKey为键,将照片存入BNRImageStore对象

[[BNRImageStore sharedStore] setImage:image

forKey:self.item.itemKey];

imageView.image = image;

[self dismissViewControllerAnimated:YES completion:nil];

}

每当BNRDetailViewController获取到UIImage对象之后,都会将其存入BNRImageStore对象。BNRImageStore对象与BNRItem对象都保存了UIImage对象的键,随时可以通过键找到需要的UIImage对象。

类似地,在用户删除了某个BNRItem对象后,需要同时在BNRImageStore对象中删除对应的UIImage对象。在BNRDetailViewController.m顶部导入BNRImageStore.h,然后修改removeItem:方法,代码如下:

#import “BNRImageStore.h”

@implementation BNRItemStore

- (void)removeItem:(BNRItem *)item

{

NSString *key = item.itemKey;

[[BNRImageStore sharedStore] deleteImageForKey:key];

[self.privateItems removeObjectIdenticalTo:item];

}

读者也许会问,为什么不直接为BNRItem添加一个属性指向UIImage对象呢?这样不就可以直接处理UIImage对象了吗?虽然目前确实可以这么做,但是当本书第18章升级Homepwner,将BNRItem对象与UIImage对象存入文件系统时,就会遇到问题。

系统在创建了一个UIImage对象后,会将其保存在某块内存区域中,该内存区域有一个地址,称为内存地址。如果没有将UIImage对象从内存移动至文件系统,那么UIImage对象的内存地址将保持不变,确实可以通过添加一个UIImage属性,访问该属性指向的内存地址,找到对应的UIImage对象;但是,如果将UIImage对象存入文件系统,当应用重新启动时(第18章会详细介绍应用的生命周期),就需要将UIImage对象从文件系统载入内存,这时UIImage对象的内存地址会发生变化,无法使用之前的内存地址找到该对象。相反,如果使用键关联UIImage对象,BNRImageStore会先根据键在文件系统中找到对应的UIImage对象,然后将其载入内存,返回新的UIImage对象指针。因此,使用键可以正确地持久化保存UIImage对象。