18章 Saving,Loading and Application States
Application Sandbox
Constructing a file path
NSKeyedArchiver and NSKeyedUnarchiver
Application States and Transitions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
存档
1.Archiving,永久存储数据。
Archiving:记录并存储属性
Unarchiving:从数据中重新重新创建对象。
实现NSCoding协议,实现两个方法 encodeWithCoder:, initWithCoder:
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.itemName forKey:@"itemName"];
[aCoder encodeObject:self.serialNumber forKey:@"serialNumber"];
[aCoder encodeObject:self.dateCreated forKey:@"dateCreated"];
[aCoder encodeObject:self.itemKey forKey:@"itemKey"];
[aCoder encodeInt:self.valueInDollars forKey:@"valueInDollars"];
}
-(instancetype) initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if(self){
_itemName = [aDecoder decodeObjectForKey:@"itemName"];
}
return self;
}
2.应用沙箱, Application sandbox
程序的数据,缓存等。 不能访问其他应用的沙箱
!!!!!!!!!存储路径!!!!!!!!!!
-(NSString *)itemArchivePath
{
NSArray *documentDirectories =
NSSearchPathForDirectoriesInDomain(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentDirectiry = [documentDirectories firstObject];
return [documentDirectories stringByAppendingPathComponent:@"items.archive"];
}
**************上面的到了存储的路径,以及药存储的模型数据。那什么时候出发存储已经什么时候加载数据呢?******************
1.存储:
使用NSKeyedArchiver when application exits.
eg. BNRItem
-(BOOL) saveChanges
{
NSString *path = [self itemArchivePath];
return [NSKeyedArchiver archiveRootObject:self.privateItems];
}
!archiveRootObject:toFile: 工作流程:
1.创建NSKeyedArchiver 对象
2.privateItems发送消息 encodeWithCoder: 并且把 NSKeyedArchiver的对象作为参数。
3.privateItems发送每个其中的字对象 encodeWithCoder,并且传入 NSKeyedArchiver
4.NSKeyedArchiver 写数据到系统文件夹中
当按下home键,applicationDidEnterBackground:会发送到applicationDelegate中,你可以在其中调用saveChanges
它会存在系统文件夹下,一个document文件夹中 item.archive
加载!!:
-(instancetype)initPrivate
{
self = [super init];
if(self){
NSString *path = [self itemArchivePath];
_privateItems = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
if(!_privateItems){
_privateItems = [[NSMutableArray alloc] init];
}
}
return self;
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
~~~~~~~~~~~~~~~~~~
Application State and Transitions
Writing to the Filesystem with NSData
NSNotificationCenter and Low-Memory Warnings
Model-View-Controller Store Design Pattern
Cur:Application States Transitions
Cur:Reading and Writing to the Filesystem
Cur:the application bundle
Application State and Transitions
当按下home键,应用进入后台,进入 background state,理解应用时如何在各个状态之间切换的:
Not Running
-->Application Launches
application:willFinishLaunchingWithOptions:
application:didFinishLaunchingWithOptions:
applicationDidBecomeActive:
Active
-->Home Button Pressed or incoming phone call
applicationWillResignActive:
Inactive
--->applicationDidEnterBackground:
Background
---> After 5 seconds
Suspended
--->Application icon tapped
applicationWillEnterForeground:applicationDidBecomeActive:
---> system runs low on memory
当状态变化时,delegate会收到以上的一些信息,你可以在其中做些操作,比如保存数据等,
用NSData写入数据
保存图片
-(NSString *)imagePathForKey:(NSString *)key
{
NSArray *documentDirectories =
NSSearchPathForDirectoriesInDomain(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentDirectory = [documentDirectories firstObject];
return [documentDirectory stringByAppendingPathComponent:key];
}
// add a image to file system
-(void)setImage:(UIImage *)image forKey:(NSString *)key
{
self.dictionary[key] = image;
NSString *imagePath = [self imagePathForKey:key];
NSData *data = UIImagegJPEGRepresentation(image,0.5);
//write it to full path
[data writeToFile:imagePath atomically:YES];
}
// remove from file system
-(void)deleteImageForKey:(NSString *)key
{
if(!key){
return;
}
[self.dictionary removeObjectForKey:key];
NSString *imagePath = [self imagePathForKey:key];
[[NSFileManager defaultManager] removeItemAtPath: iamgePath error:nil];
}
// load image from system
-(UIImage *)imageForKey:(NSString *)key
{
// if posibble ,get it from dictionary
UIImage *result = self.dictionary[key];
if(!result){
NSString *imagePath = [self imagePathForKey:key];
result = [UIImage imageWithContentsOfFile:imagePath];
// replace the cache
if(result){
self.dictionary[key] = result;
}else{
NSLog(@"Error, unable to fine %@", [self imagePathForKey:key]);
}
}
return result;
}
--------------------------------
通知中心,低内存警告⚠
viewController收到 didReceiveMemoryWarning。
你可以在其中清空掉图片缓存dictionary,待需要的时候再加载
你可以添加观察者,例如在BNRImageStore中:
-(instancetype)init
{
self = [super init];
if(self){
_dictionary = [[NSMutableDictionary alloc] init];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(clearCache:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
}
return self;
}
delegate中的函数应该也是这样注册而来的
-(void)clearCache:(NSNotification *)note
{
NSLog(@"flushing %d images out of the caches",[self.dictionary count]);
[self.dictionary removeAllObjects];
}
注意,此时如果没有显示或者没有被引用到的图片缓存将清除,如果当前正在显示,则等不显示到时候再🆑清除。 需要到时候自己再手动加载。
NSNotificationCenter.每个notification都有一个名字
可以在通知中带数据, 上面note 可以访问 userInfo。像cocos2d中的事件getUserData吧
Model-View-Controller-Store
Model表示数据的模型,而Store则正在的存储数据到本地,访问数据库等。
Model表示了比如一个carItem的数据模型:
NSString *name;
NSString *productYear;
double price;
每个carItem作为store中dictionary的子项被存储到本地文件中
**当你够建一个应用程序的时候,会自动创建一个 application bundle,其中包括了所有可执行待代码,图片,音频资源等等。所有程序在执行时用到的资源
你可以通过bundle来获取资源
NSBundle *applicationBundle = [NSBundle mainBundle];
NSString *path = [applicationBundle pathForResource:@"myImage" ofType:@"png"];
这些都是只读的。不能在运行的时候修改或者添加资源,