iOS常用的几种数据存储方式

之前由于刚入行不久,对数据持久化不是很了解,尤其是用数据库存储大量数据的操作。经过摸索就在此总结一下,方便以后查阅

下面就简单介绍一下:

1.NSUserDefaults

感觉最常用的小量数据,属性,例如,账号,密码之类的;适合存储轻量级的本地数据 (个人认为这种比较简单)

NSUserDefaults支持的数据格式有:NSNumber(Integer、Float、Double),NSString,NSDate,NSArray,NSDictionary,BOOL类型

直接看代码比较容易理解:

 //    测试数据
    NSArray *myArray = [NSArray arrayWithObjects:@"hello", @"world", nil];
    NSDictionary *myDictionary = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"enuo", @"20", nil] forKeys:[NSArray arrayWithObjects:@"name", @"age", nil]];
    //    存入
    [[NSUserDefaults standardUserDefaults] setObject:myArray forKey:@"arry"];
    [[NSUserDefaults standardUserDefaults] setObject:myDictionary forKey:@"dict"];

    //这里建议同步存储到磁盘中,但是不是必须的
    [[NSUserDefaults standardUserDefaults] synchronize];

    //    读取
    NSArray *arr= [[NSUserDefaults standardUserDefaults] objectForKey:@"arry"];
    NSDictionary *dict = [[NSUserDefaults standardUserDefaults] objectForKey:@"dict"];
    NSLog(@"------%@----\n-----%@------",arr,dict);

    // 清除数据
    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"keyName"];

建议:[NSUserDefaults standardUserDefaults] 可以在项目中定义一个全局的宏,这样使用起来更便捷。

2.归档

目的是为了长时间存放有组织的数据集

(1)简单的归档方式 但是只能存储单个对象。

 //    (1)归档
    NSArray *array = [NSArray arrayWithObjects:@1,@2,@3, nil];
    NSString *filePath = [NSHomeDirectory() stringByAppendingString:@"testFile.plist"];
    BOOL success = [NSKeyedArchiver archiveRootObject:array toFile:filePath];

    NSLog(@"%d",success);
    NSLog(@"%@",filePath);

    //    (2)反归档
    NSString *filePath = [NSHomeDirectory() stringByAppendingString:@"testFile.plist"];
    id OUTarray = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
    NSLog(@"%@",OUTarray);
    

(2)可以将多个对象归档成一个文件。

 //    (1)归档
    NSMutableArray *arrayArchiver = [NSMutableArray arrayWithObjects:@"BigDragon",@"BigBiao",@"BigBaby", nil];
    NSMutableData *data = [NSMutableData data];

    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    //编码
    [archiver encodeObject:arrayArchiver forKey:@"array"];
    [archiver encodeObject:@"Jason‘s friends" forKey:@"name"];

    //编码完成之后,对象已经存储到data之中。
    [archiver finishEncoding];

    NSString *filePathtwo = [NSHomeDirectory() stringByAppendingPathComponent:@"arraytwo.plist"];
    BOOL successtwo = [data writeToFile:filePathtwo atomically:YES];
    NSLog(@"------%d",successtwo);

    //    (2)反归档

    NSString *filePathtwo = [NSHomeDirectory() stringByAppendingPathComponent:@"arraytwo.plist"];
    //读取归档数据
    NSData *dataUnarchiver = [[NSData alloc] initWithContentsOfFile:filePathtwo];

    //创建解归档对象,进行反归档
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:dataUnarchiver];

    //反归档
    NSArray *arrayUnarchiver = [unarchiver decodeObjectForKey:@"array"];
    NSLog(@"----%@",arrayUnarchiver);

    NSString *nameUnarchiver = [unarchiver decodeObjectForKey:@"name"];
    NSLog(@"-----%@",nameUnarchiver);

(3)使用工具类(感觉如果使用归档,一般使用工具类,相对来说便捷一点)

下面就先建个工具类;Person类

Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject<NSCoding>  //需要遵守NSCoding协议

@property (nonatomic,strong) NSString *name; //带归档类型
@property (nonatomic,assign) NSInteger age;
@property (nonatomic,strong) NSString *gender;

- (NSString *)description;
@end

Person.m

/**
 该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法。前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码
 */

// 归档方法
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeInteger:self.age forKey:@"age"];
    [aCoder encodeObject:self.gender forKey:@"gender"];
}
// 反归档方法
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];

    if (self != nil) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.age = [aDecoder decodeIntegerForKey:@"age"];
        self.gender = [aDecoder decodeObjectForKey:@"gender"];
    }
    return self;
}

- (NSString *)description
{
    NSString *string = [NSString stringWithFormat:@"%@\n %ld\n %@",self.name,self.age,self.gender];
    return string;
}

在控制器用的时候:

    Person *person = [[Person alloc]init];

    person.name = @"rose";
    person.age = 25;
    person.gender = @"man";

    // 归档,调用归档方法
    NSString *filePath3 = [NSHomeDirectory() stringByAppendingString:@"person.plist"];
    BOOL success3 = [NSKeyedArchiver archiveRootObject:person toFile:filePath3];
    NSLog(@"=====%d",success3);

    // 反归档,调用反归档方法
    Person *per = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath3];
    NSLog(@"=======%@",per);

3.写入文件

主要的步骤:

    //第一步:获得文件即将保存的路径:(永久保存在磁盘中)
    //    文件存储的相对目录
    NSArray *filePaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString*path = filePaths.firstObject;

    //第二步:生成在该路径下的文件:
    NSString *FileName=[path stringByAppendingPathComponent:@"flieName"];//fileName就是保存文件的文件名
    //  第三步:往文件中写入数据:    NSData *data;
    [data writeToFile:FileName atomically:YES];//将NSData类型对象data写入文件,文件名为FileName
    //  最后:从文件中读出数据:
    NSData *outdata=[NSData dataWithContentsOfFile:FileName options:0 error:NULL];//从FileName中读取出数据

下面就简单的举几个例子

#pragma mark--1.字符串写入
    //    NSString *strfilepath = [path stringByAppendingPathComponent:@"str.text"];
    NSString *strfilepath = [path stringByAppendingString:@"/text.text"];
    NSString *INstr = @"字符串写入文件";
    [INstr writeToFile:strfilepath atomically:YES encoding:NSUTF8StringEncoding error:nil];

    //    读取文件
    NSString *OUTstr  = [[NSString alloc]initWithContentsOfFile:strfilepath encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"----%@-----",OUTstr);

#pragma mark-2、数组对象写入文件
    //    构造数组plist文件的存储路径
    NSString*arrypath = [path stringByAppendingPathComponent:@"arry.plist"];
    NSArray *INarr = @[@"hahah",@"hehhe",@"heihei"];
    [INarr writeToFile:arrypath atomically:YES];

    //    读取文件
    NSArray *outarr =  [[NSArray  array]initWithContentsOfFile:arrypath];
    NSLog(@"----%@-----",outarr);

#pragma mark-3、字典对象写入文件
    NSString*dictpath = [path stringByAppendingPathComponent:@"dict.plist"];
    NSDictionary *dict = @{@"姓名":@"liuwenqiang",@"年龄":@"25",@"职业":@"ios"};
    [dict writeToFile:dictpath atomically:YES];

    //    读取文件
    NSDictionary *OUTdict =  [[NSDictionary  alloc]initWithContentsOfFile:dictpath];
    NSLog(@"----%@-----",OUTdict);

#pragma mark-4、二进制对象写入文件
    NSString *datapath = [path stringByAppendingPathComponent:@"song.m4a"];
    UIImage *image = [UIImage imageNamed:@"image"];
    NSData *imagedata = UIImageJPEGRepresentation(image, 1);
    [imagedata writeToFile:datapath atomically:YES];

    //    读取文件
    NSData *OUTdata =  [[NSData  alloc]initWithContentsOfFile:datapath];
    NSLog(@"----%@-----",OUTdata);
    

4.数据库

对于大型的数据存储,再使用上面的方法显然不适用了,该使用数据库了,我在项目中使用的是第三方的数据库FMDB,个人感觉比较好用,使用比较顺手。

那么什么是大型数据,我认为的就是那种像app里的列表之类的,由于列表的数据量相当比较大,如果像我们的应用,列表中还有列表图的话,那就更大了。

当初在看数据库之前,总感觉很难理解,不好学,但是慢慢的理解了,也并不是那么难理解,(下面的方法是需要在工具类的.h中声明的,这样控制器中才能调到)

在操作之前,需要先下载一个FMDB 拉到项目中    附上: FMDB下载地址

先创建一个工具类 fmbdTool

(1)创库建表

@implementation FmdbTool

{
    FMDatabase *db;
}
-(NSString*)createFMDBTable:(NSString *)type
{
    NSString *str;
    //1.获得数据库文件的路径
    NSString *doctorpath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];

    NSString *filePath =  [doctorpath stringByAppendingPathComponent:@"doctor.sqlite"];
//    NSLog(@"-------路径----%@-------",filePath);
    //2.获得数据库
    db = [FMDatabase databaseWithPath:filePath];
    //3.打开数据库
    if ([db open]) {
        //4.创表
        BOOL result;
        if ([type isEqualToString:@"doctor"]) {

            result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_doctor (id integer PRIMARY KEY AUTOINCREMENT,doctordict blob NOT NULL,page_ID integer NOT NULL,datacount text NOT NULL)"];

        }

        if (result) {
//            NSLog(@"====建表成功--------type=== %@",type);

            str = @"yes";

        }else
        {
            NSLog(@"====建表失败");
            str = @"no";
        }
    }else {
        NSLog(@"faile to create a FMDB");
        str = @"no";
    }

    return str;
}

在我的项目中,由于有很多的列表要做数据存储,因此我在创建库的方法中加了一个参数type,为每个要存储的页面都建一张表,并把所有的表都放到

doctor.sqlite这个库中。在创建表的时候,首先要[db open]打开数据库,该返回数据类型是bool,当为真的时候,再创建表
 result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_doctor (id integer PRIMARY KEY AUTOINCREMENT,doctordict blob NOT NULL,page_ID integer NOT NULL,datacount text NOT NULL)"];
doctordict是个数字类型的数据,就是像后台返回的下面数据中,doctorInfoList字段,所以doctordict的类型是blob 。并且由于该字段不可能为空,故在建表的时候 NOT NULL 。列表做了分页请求,所以在表中把页码存储了,page_ID  integer NOT NULL。     datacount是列表总的页数。


(2)插入数据

//插数据
-(void)addDataInsetTable:(NSArray *)doctorListArry page:(NSInteger)page datacount:(NSString*)datacount type:(NSString *)type
{
    if ([db open]) {

        NSString *pagestr = [NSString stringWithFormat:@"%ld",(long)page];
        NSError *err = nil;

        NSData *jsonData  = [NSJSONSerialization dataWithJSONObject:doctorListArry options:NSJSONWritingPrettyPrinted error:&err];

        NSString *jsonStr = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];

        if ([type isEqualToString:@"doctor"]) {

            [db executeUpdate:@"INSERT INTO t_doctor (doctordict,page_ID,datacount) VALUES (?,?,?);",jsonStr,pagestr,datacount];

        }

    }
    [db open];

}

插入数据是也是 先[db open]之后才能插入数据。

通过这个方法可以看出,我直接就可以把后台返回给我的数据,responseObject[@"doctorInfoList"] 插到表中,

在插入之前,需要先把数组转成json类型的字符串,我在这里使用了,JSONKit    JSONKit下载地址

(3).取数据

-(NSArray *)outdata:(NSString *)type
{
    NSArray *dataArr;

    NSMutableArray  *aaarr = [[NSMutableArray alloc]init];
    if ([db open]) {

        if ([type isEqualToString:@"doctor"]) {
            FMResultSet  *res = [db executeQuery:@"SELECT * FROM t_doctor"];

            while (res.next) {

                NSString *s = [res stringForColumn:@"doctordict"];

                NSArray *aa = [s objectFromJSONString];

                [aaarr addObjectsFromArray:aa];
                dataArr = aaarr;

            }

        }
    }

    [db close];

    return dataArr;
}
//取出当前页数 在该type时
-(NSString *)checkoutpage:(NSString *)type
{
    NSString *str;
    if ([db open]) {

            FMResultSet *res = [db executeQuery:@"SELECT * FROM t_activesecond where type = ?",type];

            while (res.next)
            {
                str = [res stringForColumn:@"page"];
        }
    }
    [db close];

    return str;
}

(4).删除数据

//删除数据
- (void)deleteData:(NSString *)type
{

    if ([db open]) {

        if ([type isEqualToString:@"doctor"]) {
            NSString *deleteSql = [NSString stringWithFormat:@"delete from t_doctor"];
            [db executeUpdate:deleteSql];

        }
    }

    [db close];
}

我在删除数据的时候,只删除了,指定表,并没有直接把库删了,因为所以的表都在这个库里。

先写到这吧,如果哪里说错了,请指出,谢谢啦。

				
时间: 2024-10-14 13:48:02

iOS常用的几种数据存储方式的相关文章

IOS开发数据存储篇—IOS中的几种数据存储方式

IOS开发数据存储篇—IOS中的几种数据存储方式 发表于2016/4/5 21:02:09  421人阅读 分类: 数据存储 在项目开发当中,我们经常会对一些数据进行本地缓存处理.离线缓存的数据一般都保存在APP所在的沙盒之中.一般有以下几种: 1.PList(XML属性列表) 在使用plist进行数据存储和读取,只适用于系统自带的一些常用类型才能用,且必须先获取路径相对麻烦 //写入文件 NSString *doc = [NSSearchPathForDirectoriesInDomains(

Android中常用的五种数据存储方式

第一种: 使用SharedPreferences存储数据 适用范围: 保存少量的数据,且这些数据的格式非常简单:字符串型.基本类型的值.比如应用程序的各种配置信息(如是否打开音效.是否使用震动效果.小游戏的玩家积分等),解锁口 令密码等 核心原理: 保存基于XML文件存储的key-value键值对数据,通常用来存储一些简单的配置信息.通过DDMS的File Explorer面板,展开文件浏览树,很明显SharedPreferences数据总是存储在/data/data/<package name

iOS 常用四种数据存储方式

iOS 常用四种数据存储方式 在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题.将数据保存到本地,能够让程序的运行更加流畅, ,使得用户体验更好.下面介绍?一下数据保存的方式: 1.NSKeyedArchiver:采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法.前?一个方法告诉系统怎么对对象进行编码,而后?一个方法则是告诉系统怎么对对象进行解码.例如对Possession对

android五种数据存储方式

在Android中提供了如下五种数据存储方式: SharedPreferences 文件存储 SQLite数据库方式 内容提供器(ContentProvider) 网络存储 下面具体介绍一下这五种数据存储方式的用法. 1. SharedPreferences SharedPreferences是android平台上的一个轻量级存储类,主要保存一些常用的配置信息.可以保存long.int.String类型数据. SharedPreferences以键值对方式读取和存入,最终会以XML方式保存数据,

IOS的四种数据存储方式和优略

IOS有四种常用数据存储方式: 第一种方法:用NSUserDefaults存储配置信息 NSUserDefaults被设计用来存储设备和应用的配置信息,它通过一个工厂方法返回默认的.也是最常用到的实例对象.这个对象中储存了系统中用户的配置信息,开发者可以通过这个实例对象对这些已有的信息进行修改,也可以按照自己的需求创建新的配置项.他在IOS6之后已经在文件沙盒中看不到它的信息了,所以可以存储机密信息(用户名和密码)密码,防止手机系统被破解后看你的沙盒子文件.一般这种方法存储少量信息,若是存储大量

IOS的四种数据存储方式及优劣

IOS有四种经常使用数据存储方式: 第一种方法:用NSUserDefaults存储配置信息 NSUserDefaults被设计用来存储设备和应用的配置信息.它通过一个工厂方法返回默认的.也是最经常使用到的实例对象. 这个对象中储存了系统中用户的配置信息,开发人员能够通过这个实例对象对这些已有的信息进行改动.也能够依照自己的需求创建新的配置项. 他实际上是存储于文件沙盒中的一个.plist文件,而且没有被系统加密,仅仅是ios6以后不是存于经常使用的文档文件夹下,所以不破解系统是看不到该文件的.所

对比iOS中的四种数据存储

你是用什么方法来持久保存数据的?这是在几乎每一次关于iOS技术的交流或讨论都会被提到的问题,而且大家对这个问题的热情持续高涨.本文主要从概念上把“数据存储”这个问题进行剖析,并且结合各自特点和适用场景给大家提供一个选择的思路,并不详细介绍某一种方式的技术细节. 谈到数据储存,首先要明确区分两个概念,数据结构和储存方式.所谓数据结构就是数据存在的形式.除了基本的NSDictionary.NSArray和NSSet这些对象,还有更复杂的如:关系模型.对象图和属性列表多种结构.而存储方式则简单的分为两

iOS 四种数据存储方式

NSKeyedArchiver:采用归档的形式来保存数据,该数据对象需要 遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法.前一个方法告诉系统怎么对 对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码.例如对Possession对象归档保存. NSUserDefaults:用来保存应用程序设置和属性.用户保存的数 据.用户再次打开程序或开机后这些数据仍然存在.NSUserDefaults可以存储的数据类型包括:NSDat

Android中的5种数据存储方式

Ref:http://www.cnblogs.com/hanyonglu/archive/2012/03/01/2374894.html 1 SharedPreferences存储数据 2 文件存储数据 3 SQLite数据库存储数据 4 ContentProvider存储数据 5 网络存储数据 LitePal是一款开源的Android数据库框架,它采用了对象关系映射(ORM)的模式,并将我们平时开发时最常用到的一些数据库功能进行了封装,使得不用编写一行SQL语句就可以完成各种建表.増删改查的操