最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

给Your Second iOS App:BirdWatching添加支持程序退出后,用户数据仍然保留

iOS crifan 2220浏览 0评论

之前已经实现了:

给Your Second iOS App:BirdWatching添加支持用户自定义图片

现在继续参考:

Your Second iOS App – Next Steps – Add More Functionality

的建议:

Make the master list persistent so that the user’s bird sightings are displayed every time they restart the app.

去添加,当用户退出程序,数据仍然保留,这样下次用于重新启动程序,仍然可以显示之前的数据。


1.去网上搜相关的内容,找到这里:

iOS项目中如何保存用户设置信息呢?

解释的:

用户束,NSUserDefault,或者写xml文件,写plist文件,数据库,CoreData都可以。

写沙盒,数据库等等方式多呢⋯⋯

和看到:[iOS]iOS中永久保存用户数据的两个地方 中也提到了NSUserDefault

2.所以就去学习NSUserDefault,可以参考:

iOS保存数据的4种方式

但是那个教程很烂,代码都是乱凑出来的。

尤其是其中的firstName,后来还是在:

iOS SDK: 使用NSUserDefaults  ( 后来找到了老外的原帖:iOS SDK: Working with NSUserDefaults

找到的。

3.简单看了NSUserDefault,觉得还是有点不会用。

因为现在的情况是,当前的是一个数组,每个变量都是:

BirdSighting类型,其包括几个变量:

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *location;
@property (nonatomic, strong) NSDate *date;
@property (nonatomic) UIImage *image;

即包括四个变量,两个NSString,一个NSDate,一个UIImage

如果直接把数组中的每个BirdSighting的每个变量都是一点点保存,效率太低,逻辑也很混乱。

所以还是要想办法找到个方便,可以一起行保存整个数组的,包括每个BirdSighting中所包含的数据(字符的值,data的值,图片的数据)。

4.所以就又去找,找到一些参考资料:

Save NSArray to NSUserDefaults issues (using custom object in array)

所以继续去学习NSKeyedArchiver,然后找到官网资料:

NSKeyedArchiver Class Reference

Archives and Serializations Programming Guide

然后也才知道,我所一直想要找的,Mac中的,类似于微软的C#中的序列化和反序列化,就是这个Archives。

5。看了半天教程,也还是很晕。

所以干脆参考:

How to store custom objects in NSUserDefaults

去实现代码。

最后显示试了如下代码:

-(void)initializeDefaultDataList{  
    NSMutableArray *sightingList = [[NSMutableArray alloc] init];
    self.masterBirdSightingList = sightingList;
    //[self addBirdSightingWithName:@"Pigeon" location:@"Everywhere" date:[NSDate date] image:[UIImage imageNamed:@"defaultBirdImage.gif"] ];
    
    //restore data
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *savedEncodedData = [defaults objectForKey:@"BirdSightingList"];
    self.masterBirdSightingList = (NSMutableArray *)[NSKeyedUnarchiver unarchiveObjectWithData:savedEncodedData];
}


-(void)addBirdSightingWithName:(NSString *)inputBirdName location:(NSString *)inputLocation date:(NSDate *)date image:(UIImage *)image{
    BirdSighting *sighting;
    //NSDate *today = [NSDate date];
    //sighting = [[BirdSighting alloc]initWithName:inputBirdName location:inputLocation date:today];
    sighting = [[BirdSighting alloc]initWithName:inputBirdName location:inputLocation date:date image:image];
    [self.masterBirdSightingList addObject:sighting];

    //save data
    NSData *encodedCurBirdSightingList = [NSKeyedArchiver archivedDataWithRootObject:self.masterBirdSightingList];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:encodedCurBirdSightingList forKey:@"BirdSightingList"];
}

虽然调试过程中,可以看到encodedCurBirdSightingList是135个字节,但是最后的结果却是什么都没有显示。

很明显,只是保持了指针,但是没有保留数据,所以肯定是不显示内容的。

6.后来参考了原先官网文档的中文版:

如何编码解码对象

中的解释:

如果您期望子类实例能够进行编解码,则子类应遵循NSCoding 协议并实现 initWithCoder:以及encodeWithCoder:方法,这些方法会在程序归解档某个对象图的时候被调用

后,才明白,原来遵循NSCoding,就是实现了encodeWithCoderinitWithCoder,这样别人再去调用archivedDataWithRootObjectunarchiveObjectWithData,就会调用前面那两个函数了。

如果实现了将自定义的Object,实现了编码解码了。

7.关于如何实现自定义对象的NSMutableArray数组,保存和恢复自NSUserDefaults的逻辑和示例代码,可参考:

【已解决】iPhone/iOS中保存自定义对象(Custom Object/Custom Class)的数组(NSMutableArray/NSArray)到NSUserDefaults

 

【总结】

想要实现程序退出仍可以保留用户数据的话,可以通过将数据保存自/恢复自NSUserDefaults。

具体实现逻辑和参考代码,可参考:

【已解决】iPhone/iOS中保存自定义对象(Custom Object/Custom Class)的数组(NSMutableArray/NSArray)到NSUserDefaults

转载请注明:在路上 » 给Your Second iOS App:BirdWatching添加支持程序退出后,用户数据仍然保留

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (1)

    86 queries in 0.165 seconds, using 22.11MB memory