保存,读取,状态切换

1.应用沙盒
1.应用程序包(application bundle):包含所有的资源文件和可执行文件,只读。
2.Library/Preferences/: 存放所有的偏好设置(preferences)ios的Seting应用(设置)会在该目录中查找应用的设置信息,可通过NSUserDefault类来存取Library/Preferences下的设置。ITunes会在同步时备份。
3.tmp/: 保存应用运行时所需要的临时数据,使用完毕后再将相应的文件从该目录中删除,应用没有运行时,系统也会清除。
4.DocumentS/: 保存应用运行时生成的需要保留的数据。ITunes会备份该目录。
5.Library/Caches/: 保存应用运行时生成的需要保留的数据。ITunes不备份,因为这些数据可能会很大。
2.获取文件路径
NSArray *documentPaths =
<span style="white-space:pre">	</span>NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
<span style="white-space:pre">					</span>NSUserDomainMask,
<span style="white-space:pre">					</span>YES);
NSString *ourDocumentPath = [documentPaths objectAtIndex:0];

用NSSearchPathForDirectoriesInDomains返回一个字符串数组,其实这个数组只有一个字符串,因为该函数来源于Mac OS X,但在IOS上,一个目录类型只对应一个目录,所以这里直接获取第一个NSString对象,拿到Documents目录。
还可以通过NSHomeDirectory函数得到沙盒自身的路径。注意:系统不允许在沙盒的根目录下创建文件和目录,但可以在沙盒的已有的目录下创建新的目录或文件,这些已有目录就是Docunmets,Library,tmp。
NSString *sandboxPath = NSHomeDirectory();
// Once you have the full sandbox path, you can create a path from it
NSString *documentPath = [sandboxPath
			stringByAppendingPathComponent:@"Documents"];

用NSSearchPathForDirectoriesInDomains更安全,因为可以避免新的操作系统会修改目录名,避免拼写错误。

获取程序包:
// Get a pointer to the application bundle
NSBundle *applicationBundle = [NSBundle mainBundle];
// Ask for the path to a resource named myImage.png in the bundle
NSString *path = [applicationBundle pathForResource:@"myImage" ofType:@"png"];


3.固化(archiving)
在得到路径后,肯定是要把数据写到目录中,那么用什么方式写呢?这里先介绍achiving。
固化是将单个或多个对象从内存写入文件系统的过程,解固(unarchiving)则是从文件读取对象并写回内存。
固化通过NSCoder实例来完成,一旦NSCoder收集完所需的数据,就可以将其写入指定的文件系统中的文件。
只有遵守NSCoding协议的对象才可以固化。两个协议方法:encodeWithCoder:(固化用)和initWithCoder:(解固用)。
- (BOOL)saveChanges {
    return [NSKeyedArchiver archiveRootObject:allPossessions toFile:[self possessionArchivePath]];
}
archiveRootObject:toFile:方法会先创建一个NSKeyedArchiver实例,然后向allPossessions发送encodeWithCoder:因为allPossessions是一个数组,数组实现了协议encodeWithCoder:里面的实现应该是对数组里的每一个元素发送encodeWithCoder:(前提是元素是遵守了encodeWithCoder:协议的对象),在对象元素中实现协议方法做响应的处理(对变量进行编码,并用key-value进行保存)以达到固化的作用。
- (void)encodeWithCoder:(NSCoder *)aCoder {
    //根据变量名固化实例变量
    //如果实例变量是对象,该对象也会收到encodeWithCoder消息,这是一个递归的过程
    [aCoder encodeObject:possessionName forKey:@"possessionName"];
    [aCoder encodeObject:serialNumber forKey:@"serialNumber"];
    [aCoder encodeObject:dateCreated forKey:@"dateCreated"];
    [aCoder encodeObject:_imageKey forKey:@"imageKey"];
    
    //对于基本类型valueInDollars,必须用这个方法
    [aCoder encodeInt:valueInDollars forKey:@"valueInDollars"];
}

固化类似于一个递归过程,从根对象开始,然后是实例变量,其次是实例变量的实例变量。(UIView也遵守NSCoding协议,XIB就是依靠固化机制创建的,只不过有跟标准固化有点不一样)。
4.解固
通过NSKeyedUnarchiver的类方法unarchiveObjectWithFile:可将数据从文件系统还原至内存。传入的参数是固化的文件的路径,它会将相应的文件读入内存,然后开始一系列的解固过程。
- (void)fetchPossessionIfNecessary {

    if (!allPossessions) {
        NSString *path = [self possessionArchivePath];
        allPossessions = [[NSKeyedUnarchiver unarchiveObjectWithFile:path] retain];
    }
    if (!allPossessions) {
        allPossessions = [[NSMutableArray alloc] init];
    }
}
unarchiveObjectWithFile:会创建一个NSKeyedUnarchiver实例,解固时,系统能自动确定根对象的类,并向这个类发送alloc消息,然后向新建的未经初始化的实例发送initWithCoder:消息,并传入相应的NSKeyedUnarchiver实例。在这个例子中,首先向根对象allPossessions发送alloc,并接着发送initWithCoder:,由于allPossessions是一个数组,数组类中的initWithCoder:方法应该也是向每个元素(为对象元素时)发送alloc和initWithCoder:方法。跟固化相似解固的过程也类似于递归,所以要在元素中实现initWithCoder:代码如下:
- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    
    if (self) {
        //解码每个已固化的实例变量,然后传给相应的传方法
        [self setPossessionName:[aDecoder decodeObjectForKey:@"possessionName"]];
        [self setSerialNumber:[aDecoder decodeObjectForKey:@"serialNumber"]];
        [self setImageKey:[aDecoder decodeObjectForKey:@"imageKey"]];
        
        [self setValueInDollars:[aDecoder decodeIntForKey:@"valueInDollars"]];
        
        dateCreated = [[aDecoder decodeObjectForKey:@"dateCreated"] retain];
    }
    
    return self;
}

5.运行状态转换
先上图:


再上代码:
- (void)applicationWillTerminate:(UIApplication *)application {
	//_cmd代表所在的选择器,功能相当于self
    NSLog(@"%@",NSStringFromSelector(_cmd));
    [[PossessionStore defaultStore] saveChanges];
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    NSLog(@"%@",NSStringFromSelector(_cmd));
    [[PossessionStore defaultStore] saveChanges];
}

- (void)applicationWillResignActive:(UIApplication *)application {
    NSLog(@"%@",NSStringFromSelector(_cmd));
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    NSLog(@"%@",NSStringFromSelector(_cmd));
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    NSLog(@"%@",NSStringFromSelector(_cmd));
}

可通过以上代码来测试。

6.通过NSData来保存数据
通过NSData创建,维护和释放内存缓冲区,NSData实例可以保存一定数量的二进制数据。
- (void)setImage:(UIImage *)img forkey:(NSString *)imageKey {
    [dictionary setObject:img forKey:imageKey];
    
    //为图片创建全路径
    NSString *imagePath = pathInDocumentDirectory(imageKey);
    
    //将图片转化为JPEG数据
    NSData *dataImage = UIImageJPEGRepresentation(img, 0.5);
    
    //将JPEG数据写入文件
    [dataImage writeToFile:imagePath atomically:YES];
}

writeToFile: atomically:第二个参数是一个BOOL,当为YES时,系统会将数据写入临时文件,成功后再将文件改名为第一个参数指定的路径,并覆盖原有文件,这样,如果应用在写入文件过程中崩溃,也不会损坏现有的数据。
虽然C语言库中提供了标准I/O函数,但并不常用,因为有很多方便的途径可以读取文本和二进制文件。如NSString,NSDictionary和NSArray对象都有writeToTile:和initWithContentsOfFile:方法。NSDictionary和NSArray对象必须只包含可序列化对象(包括NSString,NSNumber,NSData,NSArray和NSDictionary)才能通过writeToTile:方法将对象存入文件。生成XML property list格式的文件。
7.内存过低警告
发生内存过低警告时,系统会向通告中心发布UIApplicationDidReceiveMemoryWarningNotification通告,凡是需要自己处理内存过低警告的对象,都可以注册并接收这个通告。
   NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter addObserver:self selector:@selector(clearCache:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值