首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

iOS开发基础135-Core Data

编程知识
2024年07月22日 13:55

Objective-C (OC) 中使用 Core Data 是iOS应用开发中管理模型层对象的一种有效工具。Core Data 使用 ORM (对象关系映射) 技术来抽象化和管理数据。这不仅可以节省时间,还能减少编程错误。以下是使用 Core Data 的详细介绍,包括示例代码,以及深入底层的一些分析。

基本概念

  1. 持久化容器 (NSPersistentContainer): iOS 10 引入的,封装了 Core Data 栈的设置,包括托管对象模型 (NSManagedObjectModel),持久化存储协调器 (NSPersistentStoreCoordinator),和上下文 (NSManagedObjectContext)。

  2. 托管对象模型 (NSManagedObjectModel): 描述应用的数据模型,包括实体(Entity)和这些实体之间的关系。

  3. 持久化存储协调器 (NSPersistentStoreCoordinator): 负责协调托管对象上下文和持久化存储。

  4. 上下文 (NSManagedObjectContext): 用于在内存中管理对象。执行创建、读取、更新、删除操作时,这些更改暂时只发生在上下文中,直到保存更改到持久层。

使用示例

以下是一个简单的使用 Core Data 创建和查询对象的示例:

步骤 1: 配置数据模型

首先,通过 Xcode 的 Data Model Editor 创建数据模型文件(.xcdatamodeld)。假设定义了一个 Person 实体,有 nameage 两个属性。

步骤 2: 设置持久化容器

在 AppDelegate 中设置持久化容器:

#import <CoreData/CoreData.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (readonly, strong) NSPersistentContainer *persistentContainer;

- (void)saveContext;

@end

@implementation AppDelegate

@synthesize persistentContainer = _persistentContainer;

// 懒加载 persistentContainer
- (NSPersistentContainer *)persistentContainer {
    // 如果容器已经被初始化了,直接返回
    if (_persistentContainer != nil) {
        return _persistentContainer;
    }
    
    // 使用名为 MyModel 的模型文件创建容器
    _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"MyModel"];
    [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
        if (error != nil) {
            // 错误处理,实际应用中应该替换为更合适的错误处理
            NSLog(@"Unresolved error %@, %@", error, error.userInfo);
            abort();
        }
    }];
    return _persistentContainer;
}
@end

步骤 3: 使用 Core Data 新增和查询

在合适的地方(如 ViewController)进行数据的新增和查询:

#import "AppDelegate.h"
#import <CoreData/CoreData.h>

- (void)insertNewPersonWithName:(NSString *)name age:(int)age {
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *context = appDelegate.persistentContainer.viewContext;
    
    // 创建新的 Person 实体对象
    NSManagedObject *newPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
    [newPerson setValue:name forKey:@"name"];
    [newPerson setValue:@(age) forKey:@"age"];
    
    NSError *error = nil;
    // 保存到持久层
    if (![context save:&error]) {
        NSLog(@"保存失败: %@, %@", error, error.userInfo);
    }
}

- (NSArray *)fetchPersons {
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *context = appDelegate.persistentContainer.viewContext;
    
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
    
    NSError *error = nil;
    NSArray *results = [context executeFetchRequest:fetchRequest error:&error];
    if (!results) {
        NSLog(@"查询失败: %@, %@", error, error.userInfo);
    }
    return results;
}

深入分析

Core Data 的底层使用了 SQLite 作为默认的持久化方式(尽管你可以选择内存或者自定义解决方案),但开发者无需直接与数据库交互,所有的操作都是通过上述的对象和 API 完成。Core Data 框架负责转换这些操作为 SQLite 命令并执行。

Core Data 性能优化

  • 批量请求: iOS 8 引入了批量删除和更新,这样可以在不加载数据到内存的情况下直接在持久层执行操作,极大提升效率。

  • 预获取: 对于频繁访问的关联对象,可以使用预获取来减少查询次数。

  • 轻量级迁移: 对于数据模型的更改,通过轻量级迁移避免手动处理数据结构变动。

封装

对于Core Data的使用,进行二次封装可以提高代码的复用性,让外部调用变得更加简洁。我们可以创建一个单例类CoreDataManager来管理Core Data的常见操作,比如增删改查。

首先,你需要确保你的数据模型(.xcdatamodeld文件)已经设置好,举个例子,这里假设我们有一个Person的Entity,它有两个属性:name(String类型)和age(Int16类型)。

步骤 1: 创建Core Data管理类

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

@interface CoreDataManager : NSObject

@property (readonly, strong) NSPersistentContainer *persistentContainer;
+ (instancetype)sharedManager;
- (void)saveContext;
- (void)insertPersonWithName:(NSString *)name age:(NSNumber *)age completion:(void(^)(BOOL success, NSError *error))completion;
- (void)fetchAllPersons:(void(^)(NSArray *persons, NSError *error))completion;

@end

@implementation CoreDataManager

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

- (NSPersistentContainer *)persistentContainer {
    @synchronized (self) {
        if (_persistentContainer == nil) {
            _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"YourModelName"];
            [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
                if (error != nil) {
                    NSLog(@"Unresolved error %@, %@", error, error.userInfo);
                    abort();
                }
            }];
        }
    }
    return _persistentContainer;
}

- (void)saveContext {
    NSManagedObjectContext *context = self.persistentContainer.viewContext;
    NSError *error = nil;
    if ([context hasChanges] && ![context save:&error]) {
        NSLog(@"Unresolved error %@, %@", error, error.userInfo);
        abort();
    }
}

- (void)insertPersonWithName:(NSString *)name age:(NSNumber *)age completion:(void(^)(BOOL success, NSError *error))completion {
    NSManagedObjectContext *context = self.persistentContainer.viewContext;
    NSManagedObject *newPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
    [newPerson setValue:name forKey:@"name"];
    [newPerson setValue:age forKey:@"age"];
    
    NSError *error = nil;
    if (![context save:&error]) {
        NSLog(@"Error saving context: %@, %@", error, error.userInfo);
        completion(NO, error);
    } else {
        completion(YES, nil);
    }
}

- (void)fetchAllPersons:(void(^)(NSArray *persons, NSError *error))completion {
    NSManagedObjectContext *context = self.persistentContainer.viewContext;
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
    
    NSError *error = nil;
    NSArray *results = [context executeFetchRequest:fetchRequest error:&error];
    if (error) {
        NSLog(@"Failed to fetch persons: %@, %@", error, error.userInfo);
        completion(nil, error);
    } else {
        completion(results, nil);
    }
}

@end

使用封装的CoreDataManager

这里展示如何使用CoreDataManager进行数据操作:

// 插入新的Person对象
[[CoreDataManager sharedManager] insertPersonWithName:@"John Doe" age:@25 completion:^(BOOL success, NSError *error) {
    if (success) {
        NSLog(@"Person added successfully");
    } else {
        NSLog(@"Failed to add person: %@", error.localizedDescription);
    }
}];

// 获取所有的Person对象
[[CoreDataManager sharedManager] fetchAllPersons:^(NSArray * _Nonnull persons, NSError * _Nonnull error) {
    if (error) {
        NSLog(@"Failed to fetch persons: %@", error.localizedDescription);
    } else {
        for (NSManagedObject *person in persons) {
            NSString *name = [person valueForKey:@"name"];
            NSNumber *age = [person valueForKey:@"age"];
            NSLog(@"Fetched person: %@, age: %@", name, age);
        }
    }
}];

通过上面的封装,我们只需调用简单的方法就可以完成对Person对象的增删改查操作,而不用关心Core Data的具体实现细节。这大大提高了代码的可读性和可维护性。

总结

Core Data 是一个功能强大的框架,通过封装复杂的底层细节,使得数据管理变得更加简单。高效地使用 Core Data 必须理解其背后的原理,并遵循最佳实践来设计应用。

From:https://www.cnblogs.com/chglog/p/18316000
本文地址: http://shuzixingkong.net/article/291
0评论
提交 加载更多评论
其他文章 Python 实现Excel和TXT文本格式之间的相互转换
Excel是一种具有强大的数据处理和图表制作功能的电子表格文件,而TXT则是一种简单通用、易于编辑的纯文本文件。将Excel转换为TXT可以帮助我们将复杂的数据表格以文本的形式保存,方便其他程序读取和处理。而将TXT转换为Excel则可以将文本文件中的数据导入到Excel中进行进一步的分析和处理。
Python 实现Excel和TXT文本格式之间的相互转换 Python 实现Excel和TXT文本格式之间的相互转换
DASCTF 2023六月挑战赛|二进制专项 PWN (上)
DASCTF 2023六月挑战赛|二进制专项 PWN (上) 1.easynote edit函数对长度没有检查 free函数存在UAF漏洞 思路:1.通过堆溢出,UAF,修改size位达到堆块重叠,使用fastbin attack,把__malloc_hook,写入one_gadget 2.通过un
DASCTF 2023六月挑战赛|二进制专项 PWN (上) DASCTF 2023六月挑战赛|二进制专项 PWN (上) DASCTF 2023六月挑战赛|二进制专项 PWN (上)
使用 useNuxtData 进行高效的数据获取与管理
title: 使用 useNuxtData 进行高效的数据获取与管理 date: 2024/7/22 updated: 2024/7/22 author: cmdragon excerpt: 深入讲解了Nuxt 3中useNuxtData组合函数的应用,演示了如何通过此函数访问缓存数据,实现组件间数
使用 useNuxtData 进行高效的数据获取与管理 使用 useNuxtData 进行高效的数据获取与管理
ScaleDet:AWS 基于标签相似性提出可扩展的多数据集目标检测器 | CVPR 2023
论文提出了一种可扩展的多数据集目标检测器(ScaleDet),可通过增加训练数据集来扩大其跨数据集的泛化能力。与现有的主要依靠手动重新标记或复杂的优化来统一跨数据集标签的多数据集学习器不同,论文引入简单且可扩展的公式来为多数据集训练产生语义统一的标签空间,通过视觉文本对齐进行训练,能够学习跨数据集的
ScaleDet:AWS 基于标签相似性提出可扩展的多数据集目标检测器 | CVPR 2023 ScaleDet:AWS 基于标签相似性提出可扩展的多数据集目标检测器 | CVPR 2023 ScaleDet:AWS 基于标签相似性提出可扩展的多数据集目标检测器 | CVPR 2023
R语言基于表格文件的数据绘制具有多个系列的柱状图与直方图
本文介绍基于R语言中的readxl包与ggplot2包,读取Excel表格文件数据,并绘制具有多个系列的柱状图、条形图的方法~
R语言基于表格文件的数据绘制具有多个系列的柱状图与直方图 R语言基于表格文件的数据绘制具有多个系列的柱状图与直方图 R语言基于表格文件的数据绘制具有多个系列的柱状图与直方图
入门到精通rsync和inotify
rsync 作用: 实现文件的备份 备份位置可以是当前主机,也可以是远程主机 备份过程可以是完全备份,也可以是增量备份 功能: 1)类似于cp的复制功能 将本地主机的一个文件复制到另一个位置下 2)将本地主机的文件推送到远程主机: 也可以是从远程主机拉取文件到本地 使用模式: shell模式: 就是
🚀RabbitMQ+redis+Redisson分布式锁+seata实现订单服务
引言 订单服务涉及许多方面,分布式事务,分布式锁,例如订单超时未支付要取消订单,订单如何防止重复提交,如何防止超卖、这里都会使用到。 开启分布式事务可以保证跨多个服务的数据操作的一致性和完整性, 使用分布式锁可以确保在同一时间只有一个操作能够成功执行,避免并发引起的问题。 订单流程(只展示重要的内容
张高兴的 MicroPython 入门指南:(三)使用串口通信
目录什么是串口使用方法使用板载串口相互通信硬件需求电路代码使用板载的 USB 串口参考 什么是串口 串口是串行接口的简称,这是一个非常大的概念,在嵌入式中串口通常指 UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)。使用串口进行的通信
张高兴的 MicroPython 入门指南:(三)使用串口通信 张高兴的 MicroPython 入门指南:(三)使用串口通信 张高兴的 MicroPython 入门指南:(三)使用串口通信