zoukankan      html  css  js  c++  java
  • iOS开发UI篇—ios应用数据存储方式(归档)

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

    具有这个方法的类有:

    NSArray
    NSMutableArray
    NSDictionary
    NSMutableDictionary
    NSData
    NSMutableData
    NSString
    NSMutableString
    NSNumber
    NSDate

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

    [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,向其中添加属性,以及协议:

    #import <Foundation/Foundation.h>
    
    @interface ArchivingData : NSObject <NSCoding, NSCopying>
    
    @property (copy, nonatomic) UIImage *image;
    @property (copy, nonatomic) NSString *name;
    @property (copy, nonatomic) NSString *gender;
    @property (copy, nonatomic) NSString *vocation;
    @property (copy, nonatomic) NSString *page;
    @property float theSlider;
    @property BOOL isSwitchOn;
    
    @end

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

    5.1 在@implementation之前添加代码:

    #define kImageKey @"ImageKey"
    #define kNameKey @"NameKey"
    #define kGenderKey @"GenderKey"
    #define kVocationKey @"VocationKey"
    #define kPageKey @"PageKey"
    #define kTheSliderKey @"TheSliderKey"
    #define kIsSwitchOn @"IsSwitchOnKey"

    5.2 在@implementation之后添加代码:

    @synthesize image;
    @synthesize name;
    @synthesize gender;
    @synthesize vocation;
    @synthesize page;
    @synthesize theSlider;
    @synthesize isSwitchOn;

    5.3 在@end之前添加代码:

    #pragma mark NSCoding
    - (void)encodeWithCoder:(NSCoder *)aCoder {
        [aCoder encodeObject:image forKey:kImageKey];
        [aCoder encodeObject:name forKey:kNameKey];
        [aCoder encodeObject:gender forKey:kGenderKey];
        [aCoder encodeObject:vocation forKey:kVocationKey];
        [aCoder encodeObject:page forKey:kPageKey];
        [aCoder encodeFloat:theSlider forKey:kTheSliderKey];
        [aCoder encodeBool:isSwitchOn forKey:kIsSwitchOn];
        
    }
    
    - (id)initWithCoder:(NSCoder *)aDecoder {
        if (self = [super init]) {
            image = [aDecoder decodeObjectForKey:kImageKey];
            name = [aDecoder decodeObjectForKey:kNameKey];
            gender = [aDecoder decodeObjectForKey:kGenderKey];
            vocation = [aDecoder decodeObjectForKey:kVocationKey];
            page = [aDecoder decodeObjectForKey:kPageKey];
            theSlider = [aDecoder decodeFloatForKey:kTheSliderKey];
            isSwitchOn = [aDecoder decodeBoolForKey:kIsSwitchOn];
        }
        return self;
    }

    5.4 在@end之前添加代码:

    #pragma mark NSCoping
    - (id)copyWithZone:(NSZone *)zone {
        ArchivingData *copy = [[[self class] allocWithZone:zone] init];
        copy.image = self.image;
        copy.name = [self.name copyWithZone:zone];
        copy.gender = [self.gender copyWithZone:zone];
        copy.vocation = [self.vocation copyWithZone:zone];
        copy.page = [self.page copyWithZone:zone];
        copy.theSlider = self.theSlider;
        copy.isSwitchOn = self.isSwitchOn;
        return copy;
    }

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

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

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

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

    7.1 在@implementation之后添加代码:

    @synthesize archivingFilePath;

    7.2 在#import之后添加代码:

    #import "ArchivingData.h"
    
    #define kArchivingFileKey @"archivingFile"
    #define kArchivingDataKey @"ArchivingDataKey"

    7.3 在viewDidLoad方法中添加代码:

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

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

    - (IBAction)switchImage:(id)sender {
        UIImage *image1 = [UIImage imageNamed:@"boy.png"];
        UIImage *image2 = theImageView.image;
        if (![image1 isEqual:image2]) {
            theImageView.image = image1;
        } else {
            theImageView.image = [UIImage imageNamed:@"gemini.png"];
        }
    }

    7.5 在@end之前添加代码:

    //程序进入后台时,保存设置
    - (void)applicationWillResignActive:(NSNotification *)notification {
        ArchivingData *archivingData = [[ArchivingData alloc] init];
        archivingData.image = self.theImageView.image;
        archivingData.name = self.nameTextField.text;
        archivingData.gender = self.genderTextField.text;
        archivingData.vocation = self.vocationTextField.text;
        archivingData.page = self.pageTextField.text;
        archivingData.theSlider = theSlider.value;
        archivingData.isSwitchOn = theSwitch.on;
        NSMutableData *data = [[NSMutableData alloc] init];
        NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
        [archiver encodeObject:archivingData forKey:kArchivingDataKey];
        [archiver finishEncoding];
        [data writeToFile:self.archivingFilePath atomically:YES];
    }

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

    9、运行程序

    刚运行程序如下左图:

       

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

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

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

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

  • 相关阅读:
    IE10/IE9 Click Enter will trigger submission
    错误代码以及错误消息提示-如何更好地管理与维护消息资源
    Redmine2.6.1 升级与Agile插件安装
    编译安装的 mysql apache 用 service mysqld start 来启动
    编译安装php 5.5 缺少依赖包 及解决方案
    linux 下mysql的启动 、调试、排错
    linux 的 磁盘操作
    mysql 触发器的创建 修改 删除
    创建mysql存储过程,调用 及删除
    存储函数的创建 删除 修改
  • 原文地址:https://www.cnblogs.com/iosblogx/p/4474238.html
Copyright © 2011-2022 走看看