IOS开发-数据库总结

关于数据存储概念:

数据结构:

基本对象:NSDictionary、NSArray和NSSet这些对象。
复杂对象:关系模型、对象图和属性列表多种结构等。
存储方式:

内存:内存存储是临时的,运行时有效的,但效率高。
闪存:闪存则是一种持久化存储,但产生I/O消耗,效率相对低。
归档:把内存数据转移到闪存中进行持久化的操作的过程。

常用的数据存储方案:

属性列表:NSArray、NSDictionary、NSData、NSString、NSNumber、NSDate等
        基本数据类型都支持这个机制,NSUserDefaults 也属于属性列表存储,常用

        于存储配置信息。这个机制可以将这些对象直接序列化到 plist 文件中,多用

        于少量数据的存储,效率较高。
        

// NSUserDefaults 默认
    NSUserDefaults *userDefaults =  [NSUserDefaults standardUserDefaults];
    [userDefaults setObject:@"skyming" forKey:@"username"];
    [userDefaults setObject:[NSDate date] forKey:@"date"];
    [userDefaults setObject:@[@"a1",@"a2"] forKey:@"array"];
    [userDefaults setInteger:6174 forKey:@"code"];
    NSLog(@"userDefaults: %@",[userDefaults dictionaryRepresentation]);

    NSString *username = [userDefaults objectForKey:@"username"];
    NSDate *date = [userDefaults objectForKey:@"date"];
    NSArray *array = [userDefaults objectForKey:@"array"];
    NSInteger code = [userDefaults integerForKey:@"code"];

    NSLog(@"username: %@  date:%@  \n array: %@ code: %d", username, date, array, code);
    [userDefaults synchronize];
    // NSUserDefaults 自定义
    NSUserDefaults *defaults = [[NSUserDefaults alloc] init];
    [defaults setPersistentDomain:[NSDictionary dictionaryWithObject:@"Hello" forKey:@"World"] forName:@"com.Sensoro.DefaultsTest"];
    [defaults synchronize];

//  数组
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
    NSString *docPath = [paths objectAtIndex:0];  
    NSString *myFile = [docPath stringByAppendingPathComponent:@"my.list"];  
    //读取文件  
    NSArray *array = [[NSArray alloc] initWithContentsOfFile:myFile];  
    //操作完若修改了数据则,写入文件  
    [array writeToFile:myFile atomically:YES];
  • 对象归档:

自定义对象常用的存储机制,对象必须实现 NSCoding 协议,NSCopying协议可选
simple code

#pragma mark -
#pragma NSCoding协议实现实现
- (void)encodeWithCoder:(NSCoder *)aCoder
{   //encoder
    [aCoder encodeObject:self.username forKey:@"username"];
    [aCoder encodeObject:self.password forKey:@"password"];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
    //decoder
    if (self = [super init]) {
        self.username = [aDecoder decodeObjectForKey:@"username"];
        self.password =  [aDecoder decodeObjectForKey:@"password"];
    }
    return self;
}

#pragma NSCopying协议实现
- (id)copyWithZone:(NSZone *)zone
{
    DSObj *copy = [[[self class] allocWithZone:zone] init];
    return copy;
}

// 读取    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docPath = [paths objectAtIndex:0];
    NSString *myFile = [docPath stringByAppendingPathComponent:@"dsObj.list"];

    //写入归档文件
    NSMutableData *datawrite = [[NSMutableData alloc] init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:datawrite];
    [archiver encodeObject:test forKey:@"data"];
    [archiver finishEncoding];
    [datawrite writeToFile:myFile atomically:YES];

    //读取归档文件
    NSData *data = [[NSMutableData alloc] initWithContentsOfFile:myFile];
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    DSObj *testread = [unarchiver decodeObjectForKey:@"data"];
    [unarchiver finishDecoding];
    NSLog(@"DSObjRead: %@ %@",[testread username], [testread password]);

当属性多时总不能一个个的添加吧,个人偏向于使用基于运行时的一个方案:
需要归档的对象只需要继承即可。

  1. SQLite: 用于存储查询需求较多的数据  
    iOS的SDK里预置了SQLite3的库,开发者可以自建SQLite数据库。SQLite每次写入数据

都会产生IO消耗,把数据归档到相应的文件。SQLite擅长处理的数据类型其实与NSUser-

Defaults差不多,也是基础类型的小数据,只是从组织形式上不同。开发者可以以关系型

数据 库的方式组织数据,使用SQL DML来管理数据。一般来说应用中的格式化的文本类

数据可以存放在数据库中,尤其是类似聊天记录、Timeline等这些具有条件查询和排序需

求的数据。每一个数据库的句柄都会在内存中都会被分配一段缓存,用于提高查询效率。

另一个方面,由于查询缓存,当产生大量句柄或数据量较大时,会出现缓存过大,造成

内存浪费。

//open database
- (void)openDataBase
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docPath = [paths objectAtIndex:0];
    NSString *myFile = [docPath stringByAppendingPathComponent:@"data.db"];

    if (sqlite3_open([myFile UTF8String], &database)==SQLITE_OK)
    {
        NSLog(@"open sqlite db ok.");
    }
    else
    {
        NSLog( @"can not open sqlite db " );

        //close database
        sqlite3_close(database);
    }
}

//create table
- (void)createTable
{
    char *errorMsg;
    const char *createSql="create table if not exists persons (id integer primary key autoincrement,name text)";

    if (sqlite3_exec(database, createSql, NULL, NULL, &errorMsg)==SQLITE_OK)
    {
        NSLog(@"create ok.");
    }
    else
    {
        NSLog( @"can not create table" );
        [self ErrorReport:[NSString stringWithFormat:@"%s",createSql]];
    }
}


//insert table
- (void)insertTable
{
    char *errorMsg;

    const char *insertSql="insert into persons (name) values ('skyming')";
    if (sqlite3_exec(database, insertSql, NULL, NULL, &errorMsg)==SQLITE_OK)
    {
        NSLog(@"insert ok.");
    }
    else
    {
        NSLog( @"can not insert it to table" );
        [self ErrorReport:[NSString stringWithFormat:@"%s",insertSql]];
    }
}

//query table
- (void)queryTable
{
    const char *selectSql="select id,name from persons";
    sqlite3_stmt *statement;
    if (sqlite3_prepare_v2(database, selectSql, -1, &statement, nil)==SQLITE_OK)
    {
        NSLog(@"select ok.");
        while (sqlite3_step(statement)==SQLITE_ROW)//SQLITE_OK SQLITE_ROW
        {
            int _id=sqlite3_column_int(statement, 0);
            NSString *name=[[NSString alloc] initWithCString:(char *)sqlite3_column_text(statement, 1) encoding:NSUTF8StringEncoding];
            NSLog(@"row>>id %i, name>> %@",_id,name);
        }

    }
    else
    {
        //error
        [self ErrorReport:[NSString stringWithFormat:@"%s",selectSql]];
    }

    sqlite3_finalize(statement);
}

//delete table
- (void)deleteTable
{
    char *errorMsg;
    [self openDataBase];

    const char *sql = "DELETE FROM persons where id=24";
    if (sqlite3_exec(database, sql, NULL, NULL, &errorMsg)==SQLITE_OK)
    {
        NSLog(@"delete ok.");
    }
    else
    {
        NSLog( @"can not delete it" );
        [self ErrorReport:[NSString stringWithFormat:@"%s",sql]];
    }

}
//error
- (void)ErrorReport: (NSString *)item
{
    char *errorMsg;

    if (sqlite3_exec(database, [item cStringUsingEncoding:NSUTF8StringEncoding], NULL, NULL, &errorMsg)==SQLITE_OK)
    {
        NSLog(@"%@ ok.",item);
    }
    else
    {
        NSLog(@"error: %s",errorMsg);
        sqlite3_free(errorMsg);
    }
}

SQLite的使用起来要比NSUserDefaults复杂的多,因此建议开发者使用SQLite要

搭配一个操作控件使用,可以简化操作。gaosboy 开发的SQLight是一款对SQLit

e操作的封装,把相对复杂的SQLite命令封装成对象和方法,可以供大家参考。

链接地址:https://github.com/gaosboy/SQLight

Github 星比较多的方案:FMDB

链接地址:https://github.com/ccgus/fmdb

CoreData,用于规划应用中的对象
官方给出的定义是,一个支持持久化的,对象图和生命周期的自动化管理方案。严格

意义上说CoreData是一个管理方案,他的持久化可以通过 SQLite、XML或二进制

文件储存。如官方定义所说,CoreData的作用远远不止储存数据这么简单,它可以

把整个应用中的对象建模并进行自动化的 管理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值