iOS本地持久化问题

iOS持久化

在iOS开发中我们经常会遇到数据的存储问题,在iOS中我们常用的数据存储方式有 plist存储,偏好设置,归档以及数据库存储。

在学习持久化之前我们先了解一下数据常用的存储路径

源文件路径

NSString *path = [[NSBundle mainBundle] bundlePath];

Documents
最常用的目录,iTunes同步该应用时会同步此文件夹中的内容,适合存储重要数据。

NSString *path1 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;

Library/Caches:
iTunes不会同步此文件夹,适合存储体积大,不需要备份的非重要数据。通常保存应用的设置信息。

 NSString *path2 = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;

tmp:

iTunes不会同步此文件夹,系统可能在应用没运行时就删除该目录下的文件,所以此目录适合保存应用中的一些临时文件,用完就删除。

NSString *path3 = NSTemporaryDirectory();

好了,下面进入我们的正题,数据持久化

-plist存储

该存储方式只能对基本类型的数据进行持久化如:

 NSArray;
 NSMutableArray;
 NSDictionary;
 NSMutableDictionary;
 NSData;
 NSMutableData;
 NSString;
 NSMutableString;
 NSNumber;
 NSDate;

存储时使用writeToFile: atomically:方法。 其中atomically表示是否需要先写入一个辅助文件,再把辅助文件拷贝到目标文件地址。这是更安全的写入文件方法,一般都写YES。
读取时使用arrayWithContentsOfFile:方法。

//1.获得文件路径
    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
    NSString *fileName = [path stringByAppendingPathComponent:@"123.plist"];

    //2.存储

    NSArray *array = @[@"123", @"456", @"789"];
    [array writeToFile:fileName atomically:YES];

    // 3.读取
    NSArray *result = [NSArray arrayWithContentsOfFile:fileName];
    NSLog(@"%@", result);

-偏好设置

偏好设置是专门用来保存应用程序的配置信息的,一般不要在偏好设置中保存其他数据。
如果没有调用synchronize方法,系统会根据I/O情况不定时刻地保存到文件中。所以如果需要立即写入文件的就必须调用synchronize方法。
偏好设置会将所有数据保存到同一个文件中。即preference目录下的一个以此应用包名来命名的plist文件。

//1.获得NSUserDefaults文件
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    //2.向文件中写入内容
    [userDefaults setObject:@"AAA" forKey:@"a"];
    [userDefaults setBool:YES forKey:@"sex"];
    [userDefaults setInteger:21 forKey:@"age"];

    //2.1立即同步
    [userDefaults synchronize];

    //3.读取文件
    NSString *name = [userDefaults objectForKey:@"a"];
    BOOL sex = [userDefaults boolForKey:@"sex"];
    NSInteger age = [userDefaults integerForKey:@"age"];
    NSLog(@"%@, %d, %ld", name, sex, age);

-归档

如果需要归档的类是某个自定义类的子类时,就需要在归档和解档之前先实现父类的归档和解档方法。
[super encodeWithCoder:aCoder][super initWithCoder:aDecoder] 方法;

必须遵循并实现NSCoding协议
保存文件的扩展名可以任意指定
继承时必须先调用父类的归档解档方法

-实现归档和解档方法

person.h

//
//  person.h
//  OC知识点整理
//
//  Created by li on 17/2/27.
//  Copyright © 2017年 李文强. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface person : NSObject
@property (strong, nonatomic)NSString*avatar;
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) NSInteger age;
@end

person.m

//
//  person.m
//  OC知识点整理
//
//  Created by li on 17/2/27.
//  Copyright © 2017年 李文强. All rights reserved.
//

#import "person.h"
@interface person()<NSCoding>  //2.设置属性

@end

@implementation person


//解档
- (id)initWithCoder:(NSCoder *)aDecoder {
    if ([super init]) {
        self.avatar = [aDecoder decodeObjectForKey:@"avatar"];
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.age = [aDecoder decodeIntegerForKey:@"age"];
    }
    return self;
}
//归档
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.avatar forKey:@"avatar"];
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeInteger:self.age forKey:@"age"];
}

@end

-实现持久化

//
//  mainViewController.m
//  OC知识点整理
//
//  Created by li on 17/2/27.
//  Copyright © 2017年 李文强. All rights reserved.
//

#import "mainViewController.h"
#import "person.h"
@interface mainViewController ()

@end

@implementation mainViewController


-(void)NSKeyedArchiver{

    //存
    NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];
    person *per=[[person alloc]init];

    per.avatar=@"123";
    per.name=@"456";
    per.age=16;
    [NSKeyedArchiver archiveRootObject:per toFile:file];


    //取
    person*per2=[NSKeyedUnarchiver unarchiveObjectWithFile:file];

}


@end

-数据库

使用数据库必须先要添加libsqlite3.tbd库

//
//  SQLite.m
//  OC知识点整理
//
//  Created by li on 17/2/27.
//  Copyright © 2017年 李文强. All rights reserved.
//

#import "SQLite.h"
#import <SQLite3.h>
@interface SQLite()



@end



@implementation SQLite

 static sqlite3*_sqlite3;

/**
 打开数据库并创建一个表
 */
- (void)openDatabase {
    //1.设置文件名
    NSString *filename = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.db"];
    //2.打开数据库文件,如果没有会自动创建一个文件
    NSInteger result = sqlite3_open(filename.UTF8String, &_sqlite3);
    if (result == SQLITE_OK) {
        NSLog(@"打开数据库成功!");
        //3.创建一个数据库表
        char *errmsg = NULL;
        sqlite3_exec(_sqlite3, "CREATE TABLE IF NOT EXISTS t_person(id integer primary key autoincrement, name text, age integer)", NULL, NULL, &errmsg);
        if (errmsg) {
            NSLog(@"错误:%s", errmsg);
        } else {
            NSLog(@"创表成功!");
        }
    } else {
        NSLog(@"打开数据库失败!");
    }
}
/**
 *  往表中插入数据
 */
- (void)insertData {
    NSString *nameStr;
    NSInteger age;

        nameStr = [NSString stringWithFormat:@"Bourne-%d", arc4random_uniform(10000)];
        age = arc4random_uniform(80) + 20;
        NSString *sql = [NSString stringWithFormat:@"INSERT INTO t_person (name, age) VALUES('%@', '%ld')", nameStr, age];
        char *errmsg = NULL;
        sqlite3_exec(_sqlite3, sql.UTF8String, NULL, NULL, &errmsg);
        if (errmsg) {
            NSLog(@"错误:%s", errmsg);

    }
    NSLog(@"插入完毕!");
}

/**
 *  从表中读取数据到数组中
 */
- (void)readData {

    char *sql = "select name, age from t_person;";
    sqlite3_stmt *stmt;
    NSInteger result = sqlite3_prepare_v2(_sqlite3, sql, -1, &stmt, NULL);
    if (result == SQLITE_OK) {
        while (sqlite3_step(stmt) == SQLITE_ROW) {
            char *name = (char *)sqlite3_column_text(stmt, 0);
            NSInteger age = sqlite3_column_int(stmt, 1);

            NSLog(@"%s %ld",name,age);
        }

    }
    sqlite3_finalize(stmt);
}
@end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值