Objective-C基础笔记整理(二)数据持久化篇


数据持久化


在项目开发过程中,我们通常会根据需求存储一些信息,所以进行数据持久化是我们开发者的必备技能包。

1、沙盒


APP默认情况下只能访问程序自己的目录,这个目录就被称之为沙盒,NSHomeDirectory() 可获取沙盒路径。

沙盒路径

  • Documents:一般用来保存需要持久化的数据,比如登录信息、搜索记录等等。
  • Library:它包含两个文件夹Caches和Preferences,Caches 保存缓存的数据,内存不足时会被清除,而Preferences 保存持久化的数据,NSUserDefaults默认存放在此文件夹。
  • SystemData:新加入的文件夹,具体存储规则 不知
  • tmp:保存一些临时数据,应该退出时会清除该数据。


2、数据持久化的几种方式


2.1、概念

  • 属性列表:plist文件存储的数据只能用NSArray或是NSDictionary读取。

  • 偏好设置:NSUserDefaults 存储的数据类型有 NSData,NSString,NSNumber,NSDate, NSArray,NSDictionary,如果要存储图片的话,需要先将图片转成NSData类型,它的缺点是无法存储自定义数据类型。

  • 归档:轻量级数据存储,数据经过归档处理会转化成二进制数据,安全性要比属性列表要高,数据归档要遵守NSCoding协议。

  • SQLite:轻量级关系数据库,结构化查询语言,不区分大小写 能够进行建表、增、删、改、查等等,一般步骤是新建一张表 –> 添加多个字段 –> 添加多行记录,可用第三方框架 FMDB

  • CoreData:iOS5之后出现的一个框架(不是数据库),它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中。

2.2、属性列表 plist文件

    //1.获取沙盒路径
    NSString *homeString = NSHomeDirectory();
    //2.拼接Documents路径
    NSString *documentsString = [homeString stringByAppendingPathComponent:@"Documents"];
    //3.建立name.plist文件
    NSString *filePath = [documentsString stringByAppendingPathComponent:@"name.plist"];

存取数据

    NSArray *data = @[@"1", @"2", @"5"];
    [data writeToFile:filePath atomically:YES];

读取数据

    NSArray *readData = [NSArray arrayWithContentsOfFile:filePath];
    NSLog(@"%@", readData);

删除数据

    NSFileManager *manager = [NSFileManager defaultManager];
    BOOL isSuccess = [manager removeItemAtPath:filePath error:nil];
    if (isSuccess) {
        NSLog(@"删除成功");
    }else {
        NSLog(@"删除失败");
    }

2.3、偏好设置 NSUserDefaults

    //模拟数据
    NSString *userName = @"王老师";
    NSString *key = @"USERNAME";
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    //存储数据
    [userDefaults setObject:userName forKey:key];

    //读取数据
    [userDefaults objectForKey:key];

    //删除数据
    [userDefaults removeObjectForKey:key];

2.4、归档 NSKeyedArchiver

    //获取文件路径 -- 获取Documents路径 除了拼接也可以直接获取
    NSString *plistPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
    plistPath = [plistPath stringByAppendingPathComponent:@"test.plist"];

保存数据 – 归档

    NSString *testString = @"123";
    NSMutableArray *array = [NSMutableArray array];
    NSData *archiverData = [NSKeyedArchiver archivedDataWithRootObject:testString];
    [array addObject:archiverData];
    [array writeToFile:plistPath atomically:YES];

读取数据 – 解档

    NSArray *unarchiveArrray = [NSArray arrayWithContentsOfFile:plistPath];
    NSData *unarchiveData = unarchiveArrray.firstObject;
    NSString *unarchiveString = [NSKeyedUnarchiver unarchiveObjectWithData:unarchiveData];
    NSLog(@"%@", unarchiveString);

删除数据

    NSFileManager *archiveManager = [NSFileManager defaultManager];
    [archiveManager removeItemAtPath:plistPath error:nil];

注:自定义数据要遵守NSCoding协议

2.5、 SQLite

创建路径

    NSString *sqliteFilePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:@"data.sqlite"];
    sqlite3 *db;

打开数据库,创建表

    if (sqlite3_open(sqliteFilePath.UTF8String, &db) != SQLITE_OK) {
        //打开失败
        NSLog(@"打开失败");
    }else {
        //创建表
    }

创建表(例子用户表:字段 name-名字、age-年龄、icon-头像


/*
         1、创建表的SQL语句 create table
         2、SQLite3支持 NULL、INTEGER(整型)、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)数据类型
         3、if not exists表示:如果不存在数据表,则新建一个, 若存在,则此命令自动退出.
         */

        // **** 创建一个用户表 User、 字段 name-名字、age-年龄、icon-头像
        NSString *creatUserTable = @"create table if not exists 'User' ( 'id' integer not null primary key autoincrement,'name' text,'age' integer,'icon' text);";
        //项目中一般不会只有一个表
        NSArray *SQL_ARR = [NSArray arrayWithObjects:creatUserTable, nil];
        for (NSString *sqlTable in SQL_ARR) {
            //执行SQL语句
            char *error;
            if (sqlite3_exec(db, sqlTable.UTF8String, nil, nil, &error) == SQLITE_OK) {
                NSLog(@"执行成功");
            }else {
                NSLog(@"SQLiteManager执行SQL语句出错:%s",error);
            }
        }

插入数据 insert into

        NSString *insertSQL = [NSString stringWithFormat:@"insert into 'User' (name,age,icon) values ('%@',%f,'%@');", @"鲁尼", 9.0, @"www.baidu.com"];
        //执行SQL语句
        char *error;
        if (sqlite3_exec(db, insertSQL.UTF8String, nil, nil, &error) == SQLITE_OK) {
            NSLog(@"插入成功");
        }else {
            NSLog(@"SQLiteManager执行SQL语句出错:%s",error);
        }

查询数据 select

        //查询表中所有的数据 distinct(去除重复的)
        NSString *selectAllSql = @"select name,age,icon from 'User'";
        //查询表中年龄小于10的
        selectAllSql = @"select * from User where age < 10";
        //执行SQL语句

        /*
          1、 参数一:数据库对象
          2、 参数二:查询语句
          3、 参数三:查询语句的长度:-1
          4、 参数四:句柄(游标对象)
         */

        sqlite3_stmt *stmt = nil;
        if (sqlite3_prepare_v2(db, selectAllSql.UTF8String, -1, &stmt, nil) != SQLITE_OK) {
            NSLog(@"准备查询失败!");
        }else {
            //开始查询数据
            //定义一个存放数据字典的可变数组
            NSMutableArray *dictArrM = [[NSMutableArray alloc] init];
            while (sqlite3_step(stmt) == SQLITE_ROW) {
                //一共获取表中所有列数(字段数)
                int columnCount = sqlite3_column_count(stmt);
                //定义存放字段数据的字典
                NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
                for (int i = 0; i < columnCount; i++) {
                    // 取出i位置列的字段名,作为字典的键key
                    const char *cKey = sqlite3_column_name(stmt, i);
                    NSString *key = [NSString stringWithUTF8String:cKey];
                    //取出i位置存储的值,作为字典的值value
                    const char *cValue = (const char *)sqlite3_column_text(stmt, i);
                    NSString *value = [NSString stringWithUTF8String:cValue];
                    //将此行数据 中此字段中key和value包装成 字典
                    [dict setObject:value forKey:key];
                }
                [dictArrM addObject:dict];
            }
            NSLog(@"%@", dictArrM);
        }

更新数据 update

        NSString *updateSql = [NSString stringWithFormat:@"update 'User' set age='%d' where icon = '%@'", 8, @"www.baidu.com"];
        //执行SQL语句
        char *updateError;
        if (sqlite3_exec(db, updateSql.UTF8String, nil, nil, &updateError) == SQLITE_OK) {
            NSLog(@"更新成功");
        }else {
            NSLog(@"SQLiteManager执行SQL语句出错:%s",updateError);
        }

删除数据 delete

        //删除数据库所有数据 delete
        NSString *deleteSql = @"delete from 'User'";
        //删除年龄为9的数据
        deleteSql = [NSString stringWithFormat:@"delete from 'User' where age='%d'", 8];

        //执行SQL语句
        char *deleteError;
        if (sqlite3_exec(db, deleteSql.UTF8String, nil, nil, &deleteError) == SQLITE_OK) {
            NSLog(@"删除成功");
        }else {
            NSLog(@"SQLiteManager执行SQL语句出错:%s",deleteError);
        }

删除表 drop

        NSString *dropSql = @"drop table if exists 'User'";

        //执行SQL语句
        char *dropError;
        if (sqlite3_exec(db, dropSql.UTF8String, nil, nil, &dropError) == SQLITE_OK) {
            NSLog(@"删除表成功");
        }else {
            NSLog(@"SQLiteManager执行SQL语句出错:%s",dropError);
        }

操作完成后,要关闭数据库

        //关闭数据库
        sqlite3_close(db);

2.6、 CoreData

建项目时 选择Use Core Data,生成 . xcdatamodeld 文件

这里写图片描述

在 . xcdatamodeld 文件中添加模型和属性,例如 User模型,属性name(姓名)和age(年龄)

这里写图片描述

一般我们会选择手动生成继承自NSManagedObject的User类,而.xcdatamodeld文件 在编译时会自动生成User类,所以我们可以选择禁用模型的自动生成功能,在Class中的Codegen改成Manul/None。

这里写图片描述

选择Create NSmanagedObject Subclass, 手动生成类文件

这里写图片描述

这里写图片描述

获取程序委托中唯一托管的对象,用于 存储,读取,删除数据

    AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    NSManagedObjectContext *context = delegate.persistentContainer.viewContext;

创建模型对象 –> 把数据存储在实体对象 –> 保存同步文件

    User *user = [NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:context];
    user.name = @"欧阳哒哒";
    user.age = 24;
    BOOL isSave = [context save:&error];
    if (isSave) {
        NSLog(@"保存成功");
    }

初始化查询类 –> 配置查询条件 –> 执行查询

     NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"User"];
    fetchRequest.predicate = [NSPredicate predicateWithFormat:@"age > 10"];
    NSArray *results = [context executeFetchRequest:fetchRequest error:&error];
    NSLog(@"%@", results);
    if (results.count > 0) {
        User *userExample = results.firstObject;
        NSLog(@"姓名 %@", userExample.name);
    }

删除,将查询的结果删除,并保存

     for (id object in results) {
        [context deleteObject:object];
    }
    BOOL isdelete = [context save:&error];
    if (isdelete) {
        NSLog(@"删除成功");
    }

2.7、本篇 Demo 在此,可点击下载。



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值