iOS数据的持久化

本文详细介绍了iOS应用中数据持久化的两种常见方式:使用plist文件和CoreData框架。通过实例展示了如何创建、解析、写入plist文件,并提供了CoreData的实体创建、数据插入、更新、查询和删除的实现。最后,通过数据管理工具类调用展示了数据操作流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

iOS应用程序数据的持久化


# 前言 一个功能丰富的应用程序,它的数据不仅存在于内存中,而是将更多的数据写入磁盘,进行持久化存储,例如存储用户的历史信息、保存游戏进度和得分情况等。 iOS数据持久化方式基本上有4种:plist属性列表、对象归档、SQLite3和Core Data。本文主要介绍如何创建和解析plist文件,以及如何使用Core Data框架对数据进行存储、查找、编辑和删除操作。 本文用OC来进行数据持久化操作

plist文件

plist文件的全名为Property List即属性列表文件,它是一种用来存储串行化后的对象文件,由于属性列表文件的扩展名为plist,因此通常被简称为plist文件。

1.创建plist文件

首先创建一个基于【Single View Application】模板的空白项目,然后【New File】一个Property List文件
在这里插入图片描述
右键【Add Row】添加一行新的键值对
在这里插入图片描述
我们设置Name:Pteer和Age:24两个键值对,设置对应的数据类型,我们看到plist支持红框中的几种数据类型
在这里插入图片描述

2.解析plist文件

    NSString *path = [[NSBundle mainBundle] pathForResource:@"demoPlist" ofType:@"plist"];
    NSDictionary *data = [[NSDictionary alloc] initWithContentsOfFile:path];
    
    NSLog(@"%@",data);

输出

2021-03-09 20:01:30.356601+0800 PListProject[64277:23229145] {
    Age = 24;
    Name = Peter;
}

3.将数据写入plist文件

    NSMutableDictionary *dictM = [[NSMutableDictionary alloc] init];
    [dictM setObject:@"Johnny" forKey:@"Name"];
    [dictM setObject:@"23" forKey:@"Age"];
    [dictM setObject:@"183" forKey:@"Height"];
    
    NSString *path = [[NSBundle mainBundle] pathForResource:@"demoPlist" ofType:@"plist"];
    [dictM writeToFile:path atomically:true];
    NSDictionary *data = [[NSDictionary alloc] initWithContentsOfFile:path];
    
    NSLog(@"%@",data);
2021-03-09 20:14:44.729928+0800 PListProject[80790:23284101] {
    Age = 23;
    Height = 183;
    Name = Johnny;
}

使用Core Data进行数据的持久化

Core Data是一个Cocoa框架,用于存储和管理应用程序中MVC模式中的模型数据。
Core Data框架中包含了Fetch Request数据查询请求、ManagedObjectContext托管对象上下文、Persistent Store Coordinate持久化存储协调器和Persistent Store持久化存储等概念。

1.创建Core Data实体并插入数据

首先要想在项目中使用Core Data技术,需要引入Core Data框架,或者在创建新项目时选中【Core Data】选项。
在这里插入图片描述
在这里插入图片描述

2.编写一个数据操作工具类

详细的代码逻辑就不一一介绍啦,基本每一块都有注释
CoreDataManager.h

//
//  CoreDataManager.h
//  PListProject
//
//  Created by homilyiosthour on 2021/3/9.
//  Copyright © 2021 homilyiosthour. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

NS_ASSUME_NONNULL_BEGIN

@interface CoreDataManager : NSObject

/// 上下文容器 存放的是所有从数据库中取出的转换成OC对象
@property (strong, nonatomic) NSManagedObjectContext * managedObjectContext;

/// 读取解析 ,momd 文件中的内容
@property (strong, nonatomic) NSManagedObjectModel * managedObjectModel;

/// 连接的类,处理数据库数据和OC数据底层的相互转换
@property (strong, nonatomic) NSPersistentStoreCoordinator * persistentStoreCoordinator;

/// 单例
+ (instancetype)sharedInstance;

/// 插入数据
/// @param dict 字典中的键值对必须要与实体中的每个名字一一对应
/// @param success 成功回调
/// @param fail 失败回调
- (void)insertNewEntity:(NSDictionary *)dict success:(void(^)(void))success fail:(void(^)(NSError *error))fail;
/// 更新方法
/// @param success 成功
/// @param fail 失败
- (void)updateEntity:(void (^)(void))success fail:(void (^)(NSError *))fail;
- (void)selectEntity:(NSArray *)selectKeys ascending:(BOOL)isAscending filterString:(NSString *)filterString success:(void(^)(NSArray *))success fail:(void (^)(NSError *))fail;
- (void)deleateEntity:(NSManagedObject *)model success:(void (^)(void))success fail:(void(^)(NSError *))fail;
@end

NS_ASSUME_NONNULL_END

CoreDataManager.m

//
//  CoreDataManager.m
//  PListProject
//
//  Created by homilyiosthour on 2021/3/9.
//  Copyright © 2021 homilyiosthour. All rights reserved.
//

#import "CoreDataManager.h"

//获取CoreData的.xcdatamodel文件的名称
static NSString * const coreDataModelName = @"CoreDataText";

//获取CoreData
static NSString * const coreDataEntityName = @"User";

//数据库
static NSString * const sqliteName = @"User.sqlite";

@implementation CoreDataManager

@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

static CoreDataManager * coreDataManager = nil;
+ (instancetype)sharedInstance{
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        coreDataManager = [[CoreDataManager alloc] init];
    });
    return coreDataManager;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone{
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (coreDataManager == nil) {
            coreDataManager = [super allocWithZone:zone];
        }
    });
    return coreDataManager;
}

- (void)insertNewEntity:(NSDictionary *)dict success:(void(^)(void))success fail:(void(^)(NSError *error))fail{
    
    //判断字典是否为空
    if(!dict||dict.allKeys.count == 0) return;
    //通过传入上下文和实体名称,创建一个名称对应的实体对象(相当于数据库一组数据,其中含有多个字段)
    NSManagedObject *entity = [NSEntityDescription insertNewObjectForEntityForName:coreDataEntityName inManagedObjectContext:self.managedObjectContext];
    //实体对象存储属性值(相当于数据库中将一个值存入对应字段)
    for (NSString *key in [dict allKeys]) {
        [entity setValue:[dict objectForKey:key] forKey:key];
    }
    //保存信息,同步数据
    NSError *error = nil;
    BOOL result = [self.managedObjectContext save:&error];
    if (!result) {
        NSLog(@"添加数据失败:%@",error);
        if (fail) {
            fail(error);
        }
    }else{
        NSLog(@"添加数据成功");
        if(success){
            success();
        }
    }
}

- (void)deleateEntity:(NSManagedObject *)model success:(void (^)(void))success fail:(void(^)(NSError *))fail{
    
    //传入要删除的实体对象
    [self.managedObjectContext deleteObject:model];
    //同步到数据库
    NSError *error = nil;
    [self.managedObjectContext save:&error];
    if (error) {
        NSLog(@"删除失败:%@",error);
        if (fail) {
            fail(error);
        }
    } else {
        NSLog(@"删除成功");
        if (success) {
            success();
        }
    }
}

- (void)selectEntity:(NSArray *)selectKeys ascending:(BOOL)isAscending filterString:(NSString *)filterString success:(void(^)(NSArray *))success fail:(void (^)(NSError *))fail{
    
    //1.初始化一个查询请求
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    //2.设置要查询的实体
    NSEntityDescription *desc = [NSEntityDescription entityForName:coreDataEntityName inManagedObjectContext:self.managedObjectContext];
    request.entity = desc;
    //3.设置查询结果排序
    if (selectKeys && selectKeys.count>0) {//如果进行了设置排序
        NSMutableArray *array = [NSMutableArray array];
        for (NSString *key in selectKeys) {
            /**e'Key'yeKeyy
                设置查询结果排序
             sequenceKey:根据某个属性(相当于数据库某个字段)来排序
             sequenceKe'y:是否升序
             */
            NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:key ascending:isAscending];
            [array addObject:sort];
        }
        if (array.count>0) {
            request.sortDescriptors = array;//可以添加多个排序描述器。然后按顺序放进数组即可
        }
    }
    //4.设置条件过滤
    if (filterString) {//如果设置了过滤语句
        
        NSPredicate *predicate = [NSPredicate predicateWithFormat:filterString];
        request.predicate = predicate;
    }
    //5.执行请求
    NSError *error = nil;
    //获得查询数据数据集合
    NSArray *objs = [self.managedObjectContext executeFetchRequest:request error:&error];
    if (error) {
        NSLog(@"失败");
        if (fail) {
            fail(error);
        }
    }else{
        NSLog(@"成功");
        if (success) {
            success(objs);
        }
    }
}

/// 更新方法
/// @param success 成功
/// @param fail 失败
- (void)updateEntity:(void (^)(void))success fail:(void (^)(NSError *))fail{
    
    NSError *error = nil;
    [self.managedObjectContext save:&error];
    if (error) {
        NSLog(@"更新失败");
        if (fail) {
            fail(error);
        }
    } else {
        if (success) {
            success();
        }
    }
}

// 懒加载
/// 属性的getter方法
- (NSManagedObjectModel *)managedObjectModel{
    if(_managedObjectModel == nil){
        //.xcdatamodeld文件 编译之后变成.model文件(.mom)文件
        NSURL *modelUrl = [[NSBundle mainBundle] URLForResource:coreDataModelName withExtension:@"momd"];
        //把文件的内容读取到managedObjectModel中
        _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelUrl];
    }
    return _managedObjectModel;
}

/// 调度者负责数据库的操作 创建数据库 打开数据 增删改查数据
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator{
    if (!_persistentStoreCoordinator) {
        //根据model创建了persistentStoreCoordinator
        _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];
        //设置数据库存放的路径
        NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:sqliteName];
        NSError *error = nil;
        //如果没有得到数据库,程序崩溃
        /*
         持久化存储库的类型:
         NSSQLiteStoreType  SQLite数据库
         NSBinaryStoreType  二进制平面文件
         NSInMemoryStoreType 内存库,无法永久保存数据
         虽然这3种类型的性能从速度上来说都差不多,但从数据模型中保留下来的信息却不一样
         在几乎所有的情景中,都应该采用默认设置,使用SQLite作为持久化存储库
         */
        //添加一个持久化存储库并设置类型和路径,NSSQLiteStoreType:SQLite作为存储库
        if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
            if (error) {
                NSLog(@"添加数据库失败:%@",error);
            }else{
                NSLog(@"添加数据库成功");
            }
            NSLog(@"错误信息:%@,%@",error,[error userInfo]);
        }
    }
    return _persistentStoreCoordinator;
}

/// 获取沙盒路径下documents文件夹的路径 NSURL
-(NSURL *)applicationDocumentsDirectory
{
    //获取沙盒路径下documents文件夹的路径 NSURL   (类似于search)
    NSLog(@"%@",[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject].absoluteString);
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

/// 容器类 存放OC的对象
- (NSManagedObjectContext *)managedObjectContext{
    if (!_managedObjectContext) {
        NSPersistentStoreCoordinator * coordinator = [self persistentStoreCoordinator];
        if (!coordinator)
        {
            return nil;
        }
        _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        //让context和coordinator关联 context可以和数据进行增删改查功能
        //设置上下文所要关联的持久化存储库
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}
@end

调用数据管理类

    //添加插入数据
    NSDictionary *dict = @{@"userName":@"wzx",@"password":@"123456"};
    [[CoreDataManager sharedInstance] insertNewEntity:dict success:^{
        NSLog(@"添加成功");
    } fail:^(NSError * _Nonnull error) {
        NSLog(@"添加失败");
    }];
    
    //查询数据
    [[CoreDataManager sharedInstance] selectEntity:nil ascending:YES filterString:nil success:^(NSArray * result) {
        NSLog(@"查询成功:%@",result);
    } fail:^(NSError * error) {
        NSLog(@"查询失败%@",error);
    }];

    //查询数据
    NSString *filterString = [NSString stringWithFormat:@"userName='wzx'"];
    [[CoreDataManager sharedInstance] selectEntity:nil ascending:YES filterString:filterString success:^(NSArray * result) {
        NSLog(@"查询成功:%@",result);
    } fail:^(NSError * error) {
        NSLog(@"查询失败%@",error);
    }];

控制台输出结果

    2021-03-15 20:49:06.495996+0800 CoreDataText[3308:350741] 添加成功
2021-03-15 20:49:06.496408+0800 CoreDataText[3308:350741] 查询成功:(
    "<User: 0x2822cc960> (entity: User; id: 0xd8940d2834044e18 <x-coredata://6B28376E-53C7-4E97-A8F2-3243DF330828/User/p1>; data: {\n    password = 123456;\n    userName = wzx;\n})"
)
2021-03-15 20:49:06.496746+0800 CoreDataText[3308:350741] 查询成功:(
    "<User: 0x2822cc960> (entity: User; id: 0xd8940d2834044e18 <x-coredata://6B28376E-53C7-4E97-A8F2-3243DF330828/User/p1>; data: {\n    password = 123456;\n    userName = wzx;\n})"
)

参考:
《iOS移动开发从入门到精通》
ios CoreData的使用(封装):https://blog.youkuaiyun.com/u013983033/article/details/83378838

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值