通过归档永久存储数据

移动开发 iOS
这次的小例子中,我们将会通过归档实现数据的保存。当程序运行时,先检查归档文件是否存在,如果存在的话就从归档文件中读取数据显示在界面上;如果归档文件不存在,就使用默认设置。当程序关闭时,会将数据存储在归档文件中,这样下次运行程序时就会显示上次的设置了。

之前有文章简单介绍了怎样在Settings程序中设置自己的程序,并实现保存,使得下次运行自己的程序时显示的还是上次的设置 项。而文章沙盒SandBox的结构介绍SandBox时,我们看到其实使用Settings程序设置后,数据是保存在一个plist文件的。

想要***保存数据,我们当然可以使用plist文件,当退出程序时,我们执行将数据写入plist文件的操作,使用writeToFile:atomically:方法。

具有这个方法的类有:

  1. NSArray 
  2. NSMutableArray 
  3. NSDictionary 
  4. NSMutableDictionary 
  5. NSData 
  6. NSMutableData 
  7. NSString 
  8. NSMutableString 
  9. NSNumber 
  10. NSDate 

例如,我们的数据存储在NSArray的一个对象array中,保存数据时执行:

  1. [array writeToFile:filePath atomically:YES]; 

其中filePath是放在SandBox中的一个plist文件的完整路径。

不过,使用plist文件还是有局限性的,例如,我们不好将一个图片存储在plist中。

这次的小例子中,我们将会通过归档实现数据的保存。当程序运行时,先检查归档文件是否存在,如果存在的话就从归档文件中读取数据显示在界面上;如果归档文件不存在,就使用默认设置。当程序关闭时,会将数据存储在归档文件中,这样下次运行程序时就会显示上次的设置了。

1、运行Xcode 4.3,新建一个Single View Application,名称为:Archiving Test:

然后将准备好的两张图片添加到工程中。

2、先进行界面设计:

单击ViewController.xib,向其中添加控件:

然后向ViewController.h中为控件建立Outlet映射和Action映射,具体是为所有的TextField、ImageView、UISlider控件和UISwitch控件建立Outlet映射,为Button建立Action映射:

3、新建一个类,用于存储我们的数据:

在菜单栏依次选择File — New — File…,在打开的窗口选择Objective-C Class:

单击Next,输入类名:ArchivingData,选择super class为NSObject:

单击Next,选好位置和分组,点击创建,完成类的建立。

4、打开ArchivingData.h,向其中添加属性,以及协议:

  1. #import <Foundation/Foundation.h> 
  2.  
  3. @interface ArchivingData : NSObject <NSCoding, NSCopying> 
  4.  
  5. @property (copy, nonatomic) UIImage *image; 
  6. @property (copy, nonatomic) NSString *name; 
  7. @property (copy, nonatomic) NSString *gender; 
  8. @property (copy, nonatomic) NSString *vocation; 
  9. @property (copy, nonatomic) NSString *page; 
  10. @property float theSlider; 
  11. @property BOOL isSwitchOn; 
  12.  
  13. @end 

5、打开ArchivingData.m,向其中添加代码:

5.1 在@implementation之前添加代码:

  1. #define kImageKey @"ImageKey" 
  2. #define kNameKey @"NameKey" 
  3. #define kGenderKey @"GenderKey" 
  4. #define kVocationKey @"VocationKey" 
  5. #define kPageKey @"PageKey" 
  6. #define kTheSliderKey @"TheSliderKey" 
  7. #define kIsSwitchOn @"IsSwitchOnKey" 

5.2 在@implementation之后添加代码:

  1. @synthesize image; 
  2. @synthesize name; 
  3. @synthesize gender; 
  4. @synthesize vocation; 
  5. @synthesize page; 
  6. @synthesize theSlider; 
  7. @synthesize isSwitchOn; 

5.3 在@end之前添加代码:

  1. #pragma mark NSCoding 
  2. - (void)encodeWithCoder:(NSCoder *)aCoder { 
  3.     [aCoder encodeObject:image forKey:kImageKey]; 
  4.     [aCoder encodeObject:name forKey:kNameKey]; 
  5.     [aCoder encodeObject:gender forKey:kGenderKey]; 
  6.     [aCoder encodeObject:vocation forKey:kVocationKey]; 
  7.     [aCoder encodeObject:page forKey:kPageKey]; 
  8.     [aCoder encodeFloat:theSlider forKey:kTheSliderKey]; 
  9.     [aCoder encodeBool:isSwitchOn forKey:kIsSwitchOn]; 
  10. - (id)initWithCoder:(NSCoder *)aDecoder { 
  11.     if (self = [super init]) { 
  12.         image = [aDecoder decodeObjectForKey:kImageKey]; 
  13.         name = [aDecoder decodeObjectForKey:kNameKey]; 
  14.         gender = [aDecoder decodeObjectForKey:kGenderKey]; 
  15.         vocation = [aDecoder decodeObjectForKey:kVocationKey]; 
  16.         page = [aDecoder decodeObjectForKey:kPageKey]; 
  17.         theSlider = [aDecoder decodeFloatForKey:kTheSliderKey]; 
  18.         isSwitchOn = [aDecoder decodeBoolForKey:kIsSwitchOn]; 
  19.     } 
  20.     return self; 

5.4 在@end之前添加代码:

  1. #pragma mark NSCoping 
  2. - (id)copyWithZone:(NSZone *)zone { 
  3.     ArchivingData *copy = [[[self class] allocWithZone:zone] init]; 
  4.     copy.image = self.image; 
  5.     copy.name = [self.name copyWithZone:zone]; 
  6.     copy.gender = [self.gender copyWithZone:zone]; 
  7.     copy.vocation = [self.vocation copyWithZone:zone]; 
  8.     copy.page = [self.page copyWithZone:zone]; 
  9.     copy.theSlider = self.theSlider; 
  10.     copy.isSwitchOn = self.isSwitchOn; 
  11.     return copy; 

在ArchivingData类中,我们添加了几个属性,这些属性与上面创建的控件是一一对应的。之后实现了几个协议方法,这些方法分别用于编码、解码和复制。

别走开,下页内容更劲爆!

#p#

6、打开ViewController.h,向其中添加属性和方法:

  1. @property (copy, nonatomic) NSString *archivingFilePath; 
  2.  
  3. - (void)applicationWillResignActive:(NSNotification *)notification; 

7、打开ViewController.m,添加代码:

7.1 在@implementation之后添加代码:

  1. @synthesize archivingFilePath; 

7.2 在#import之后添加代码:

  1. #import "ArchivingData.h" 
  2.  
  3. #define kArchivingFileKey @"archivingFile" 
  4. #define kArchivingDataKey @"ArchivingDataKey" 

7.3 在viewDidLoad方法中添加代码:

  1. - (void)viewDidLoad 
  2.     [super viewDidLoad]; 
  3.     // Do any additional setup after loading the view, typically from a nib. 
  4.     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
  5.     NSString *documentsDirectory = [paths objectAtIndex:0]; 
  6.     self.archivingFilePath = [documentsDirectory stringByAppendingPathComponent:kArchivingFileKey]; 
  7.     NSFileManager *fileManager = [NSFileManager defaultManager]; 
  8.      
  9.     if ([fileManager fileExistsAtPath:self.archivingFilePath]) { 
  10.         //如果归档文件存在,则读取其中内容,显示在界面上 
  11.         NSData *data = [[NSMutableData alloc] initWithContentsOfFile:self.archivingFilePath]; 
  12.         NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; 
  13.         ArchivingData *archivingData = [unarchiver decodeObjectForKey:kArchivingDataKey]; 
  14.         [unarchiver finishDecoding]; 
  15.         theImageView.image = archivingData.image; 
  16.         nameTextField.text = archivingData.name; 
  17.         genderTextField.text = archivingData.gender; 
  18.         vocationTextField.text = archivingData.vocation; 
  19.         pageTextField.text = archivingData.page; 
  20.         theSlider.value = archivingData.theSlider; 
  21.         theSwitch.on = archivingData.isSwitchOn; 
  22.     } else { 
  23.         //如果归档文件不存在,则设置imageView为boy.png 
  24.         theImageView.image = [UIImage imageNamed:@"boy.png"]; 
  25.     } 
  26.      
  27.     //当程序进入后台时,将当前设置项写入归档文件 
  28.     UIApplication *app = [UIApplication sharedApplication]; 
  29.     [[NSNotificationCenter defaultCenter] addObserver:self 
  30.                                              selector:@selector(applicationWillResignActive:) 
  31.                                                  name:UIApplicationWillResignActiveNotification 
  32.                                                object:app]; 

7.4 找到switchImage方法,添加代码:

  1. - (IBAction)switchImage:(id)sender { 
  2.     UIImage *image1 = [UIImage imageNamed:@"boy.png"]; 
  3.     UIImage *image2 = theImageView.image; 
  4.     if (![image1 isEqual:image2]) { 
  5.         theImageView.image = image1; 
  6.     } else { 
  7.         theImageView.image = [UIImage imageNamed:@"gemini.png"]; 
  8.     } 

7.5 在@end之前添加代码:

  1. //程序进入后台时,保存设置 
  2. - (void)applicationWillResignActive:(NSNotification *)notification { 
  3.     ArchivingData *archivingData = [[ArchivingData alloc] init]; 
  4.     archivingData.image = self.theImageView.image; 
  5.     archivingData.name = self.nameTextField.text; 
  6.     archivingData.gender = self.genderTextField.text; 
  7.     archivingData.vocation = self.vocationTextField.text; 
  8.     archivingData.page = self.pageTextField.text; 
  9.     archivingData.theSlider = theSlider.value; 
  10.     archivingData.isSwitchOn = theSwitch.on; 
  11.     NSMutableData *data = [[NSMutableData alloc] init]; 
  12.     NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; 
  13.     [archiver encodeObject:archivingData forKey:kArchivingDataKey]; 
  14.     [archiver finishEncoding]; 
  15.     [data writeToFile:self.archivingFilePath atomically:YES]; 

8、***,为了使得键盘可以关闭,我们还要添加关闭键盘的操作,参考《iOS开发4:关闭键盘》中的第2步。

9、运行程序

刚运行程序如下左图:

我们添加一些数据,更换头像,再调整Silder和Switch,如上图右。

之后,按模拟器上的Home建,使得程序在后台运行。

此时,查看程序的SandBox,可以看到程序的Documents目录下出现了文件archivingFile:

之后使用Xcode结束运行,再运行程序。程序第二次运行时,显示如上图左,这说明我们实现了数据的***存储。

责任编辑:闫佳明 来源: cocoachina
相关推荐

2009-07-17 14:51:22

.Net Micro

2018-07-19 10:56:16

Kubernetes存储架构

2018-06-21 15:14:51

Kubernetes存储容器

2010-07-22 15:33:36

BlackBerry开

2011-08-10 09:50:43

iPhoneArchive数据

2017-11-21 14:32:05

容器持久存储

2020-09-17 13:15:20

腾讯云冷数据存储

2010-04-02 15:25:40

云归档

2009-04-09 13:58:58

JavaXML存储

2009-01-19 16:09:44

NetApp赛门铁克归档

2010-04-02 15:20:18

云存储

2020-04-03 10:54:38

多云归档备份

2017-11-07 08:36:58

云计算归档存储

2020-03-25 11:37:17

存储云原生DevOps

2021-06-30 11:08:44

网络本地化漫游网络

2020-07-15 16:09:51

戴尔

2021-02-22 15:03:01

金山云归档存储数据

2011-08-01 13:28:09

Oracle归档模式非归档模式

2010-05-07 13:03:01

Oracle通过存储过

2023-11-23 15:05:02

玻璃归档存储微软
点赞
收藏

51CTO技术栈公众号