ios10.3之CoreData的详细教程

2023-11-05

首先如果要使用CoreData可以选择在初创项目时选择添加coredata,也可以选择自己添加coredata文件

系统添加coredata后会在Appdelegate类中自动添加一个persistentContainer属性,和一个saveContext方法。在.m中还为persistentContainer写了getter

- (NSPersistentContainer *)persistentContainer {
    // The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
    @synchronized (self) {
        if (_persistentContainer == nil) {
            _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"XWMyCoreDataDemo"];
            [_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]) {
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog(@"Unresolved error %@, %@", error, error.userInfo);
        abort();
    }
}
需要特别注意的是两个方法实现中都有abort()函数,这个函数会造成程序崩溃,如果是开发模式,可以利于调试,如果是已上架模式最好移除这个函数,以免影响用户体验。

然后可以找到.xcdatamodeld文件,开始添加模型,在我的demo中添加了Person和Card两个模型,详情如下

Person中添加了两个属性name和age,类型分别为String和int32_t,card中也添加了两个属性color和size,类型均为NSObject(截图时我想尝试下Decimal数据类型尝试了下,后来改成Transformable,即NSObject类型)

需要注意的是一般我们都会选择手动生成继承自NSManagedObject的Person和Card的类方便我们查看等,而.xcdatamodeld文件在编译时会自动生成同样的Person和Card类,所以我们可以选择禁用模型的自动生成功能,如下图所示,我们可以选择模型,然后找到Class中Codegen将其改成Manul/None,即可禁止其自动生成模型子类。

然后我们还可以在文件中设置两个模型的关系,如下图所示,我们可以点击relationship中的+,添加关系,

需要注意的是添加单相关系的时候inverse是不会有值的,只有双向关系,或者有其他模型引用这个模型时才会有值。

其中relationship中的值即为生成类时系统会自动生成的属性,可以看到选择属性时右方可以选择ToOne或者ToMany,即一个Person模型可以对应几个Card,如果选择一对多

那么系统会自动生成一个集合属性,并且会生成相关的添加值的方法。然后我们可以按照下图选择生成Person和Card的类文件。

生成后项目文件如下所示

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

@class Card;

NS_ASSUME_NONNULL_BEGIN

@interface Person : NSManagedObject

@end

NS_ASSUME_NONNULL_END

#import "Person+CoreDataProperties.h"
 
#import "Person+CoreDataClass.h"
#import "Card+CoreDataClass.h"

@implementation Person

@end
 
#import "Person+CoreDataClass.h"


NS_ASSUME_NONNULL_BEGIN

@interface Person (CoreDataProperties)

+ (NSFetchRequest<Person *> *)fetchRequest;

@property (nullable, nonatomic, copy) NSString *name;
@property (nonatomic) int32_t age;
@property (nullable, nonatomic, retain) NSSet<Card *> *cards;

@end
 

@interface Person (CoreDataGeneratedAccessors)
//用于添加属性值的方法
- (void)addCardsObject:(Card *)value;
- (void)removeCardsObject:(Card *)value;
- (void)addCards:(NSSet<Card *> *)values;
- (void)removeCards:(NSSet<Card *> *)values;

@end

NS_ASSUME_NONNULL_END
#import "Person+CoreDataProperties.h"
@implementation Person (CoreDataProperties)

+ (NSFetchRequest<Person *> *)fetchRequest {
	return [[NSFetchRequest alloc] initWithEntityName:@"Person"];
}

@dynamic name;
@dynamic age;
@dynamic cards;

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

@class NSObject, Person;

NS_ASSUME_NONNULL_BEGIN

@interface Card : NSManagedObject

@end

NS_ASSUME_NONNULL_END

#import "Card+CoreDataProperties.h"
#import "Card+CoreDataClass.h"
#import "Person+CoreDataClass.h"

@implementation Card

@end 
#import "Card+CoreDataClass.h"


NS_ASSUME_NONNULL_BEGIN

@interface Card (CoreDataProperties)

+ (NSFetchRequest<Card *> *)fetchRequest;

@property (nullable, nonatomic, retain) NSObject *color;
@property (nullable, nonatomic, copy) NSObject *size;
@property (nullable, nonatomic, retain) Person *owner;

@end 
NS_ASSUME_NONNULL_END
#import "Card+CoreDataProperties.h"

@implementation Card (CoreDataProperties)

+ (NSFetchRequest<Card *> *)fetchRequest {
	return [[NSFetchRequest alloc] initWithEntityName:@"Card"];
}

@dynamic color;
@dynamic size;
@dynamic owner;

@end
可以发现模型生成的类都是继承自NSManagedObject,且相关属性都使用了@dynamic,也就是系统不会自动生成getter和setter,且在使用的过程中可以发现如果 使用alloc初始化模型的时候是会报错的!

最后附上使用过程

#import "ViewController.h"
#import "Card+CoreDataClass.h"
#import "Person+CoreDataClass.h"
#import "AppDelegate.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    NSManagedObjectContext *context = delegate.persistentContainer.viewContext; //context常用
    //创建一个Person模型对象 模型对象初始化必须有一个NSEntityDescription
    Person *p = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
    p.name = @"Will";
    p.age = 24;
    //创建一个Card模型对象 
    Card *card = [NSEntityDescription insertNewObjectForEntityForName:@"Card" inManagedObjectContext:context];
    card.color = [UIColor redColor];
    card.size = NSStringFromCGSize(CGSizeMake(70, 100));
    [p addCardsObject:card];
    NSError *error = nil;
    [context save:&error];	//保存操作
    if (error) {
        NSLog(@"%@",error.userInfo);
    }
    /**    下面是查询操作,可以删除上面代码,重新运行       */
//    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"];	//初始化一个Person的查询请求
    NSFetchRequest *request = [Person fetchRequest];	//系统自动生成了获取查询请求的方法
    NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];//为请求设置排序实例
    request.sortDescriptors = @[descriptor];
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like '?il?'"];//为请求设置过滤条件
    request.predicate = predicate;
    NSArray *array = [context executeFetchRequest:request error:&error]; //根据请求执行查找,结果存于一个数组。
    for (Person *p in array) {
        NSLog(@"%@,%d,%@",p.name,p.age,p.cards);
    }
    
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end
如果对sqlite熟悉的话,可以发现查找的工作很熟悉,就相当于数据库执行"select * from Person order by name where name like '?il?'"的操作,以前系统为我们提供的context查找操作是同步的(现在默认的查找操作默认的是异步的),所以当时如果查询操作是很耗时的话,会影响性能,当时的解决办法是进行异步查询操作
NSAsynchronousFetchRequest *request = [[NSAsynchronousFetchRequest alloc]initWithFetchRequest:[Person fetchRequest] completionBlock:^(NSAsynchronousFetchResult * _Nonnull result) {
        if (result) {
            NSLog(@"%@",result.finalResult);
            NSLog(@"%@",[NSThread currentThread]);
            NSLog(@"%@",@(context.concurrencyType));
        }
    }];
    [context executeRequest:request error:&error];
但是不管是同步还是异步的查询操作都是在主线程进行的,如果想要放在子线程的话需要更改context的concurrencyType,因为concurrencyType是readonly,且没有找到相关设置方法,所以目前我采用的重新构建一个context。
NSManagedObjectContext *backContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [backContext setPersistentStoreCoordinator:context.persistentStoreCoordinator];
    
    NSAsynchronousFetchRequest *request = [[NSAsynchronousFetchRequest alloc]initWithFetchRequest:[Person fetchRequest] completionBlock:^(NSAsynchronousFetchResult * _Nonnull result) {
        if (result) {
            NSLog(@"%@",result.finalResult);
            NSLog(@"%@",[NSThread currentThread]);
            NSLog(@"%@",@(context.concurrencyType));
        }
    }];
    [backContext executeRequest:request error:&error];
如果想要删除存储的模型的话
NSFetchRequest *request = [Person fetchRequest];
    NSArray *array = [context executeFetchRequest:request error:&error];
    for (Person *p in array) {
        if ([p.name isEqualToString:@"will"]) {
            [context deleteObject:p];
            [context save:&error];
        }
    }
很重要的一点是, 每次进行操作后需要保存才能生效!


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ios10.3之CoreData的详细教程 的相关文章

  • iOS 搜索栏不显示结果

    更新 这实际上有效 我的自定义单元格的样式尚未出现 因此单元格看起来是空白的 那我怎样才能得到searchResultsTableView使用我的自定义单元格 我在表格视图中实现了搜索栏 当我调试时搜索 过滤所有工作 但是当我在搜索栏中输入
  • TestFlight 安装的应用程序因 Swift 包管理器依赖项而崩溃

    我们已经迁移了一些 CocoaPod 依赖项 以便在 Xcode 11 中使用 Swift Package Manager 进行构建和链接 但是 每当我们将应用程序提交到 AppStore Connect 并使用 TestFlight 进行
  • 聊天室成员列表

    如何检索正在使用的聊天室的成员列表XMPP framework 我尝试使用 void xmppRoom XMPPRoom sender didFetchMembersList NSArray items 但它返回一个空数组 这个问题很老了
  • 如何在 iOS swift 中集成 Google Pay?

    嗨 朋友们 我搜索过有关 iOS swift 中谷歌支付集成的信息 我没有找到任何相关的解决方案 请帮助我如何解决这个问题 如果有任何链接或示例 请提供链接并指导我 谢谢 这是关于在印度发起 Google Pay 操作的问题吗 例如 使用
  • 4.4 中新的 Objective-c 文字

    我可以写 42 这会创建一个NSNumber with int值 42 我可以用变量来做到这一点 例如 someIntVar 显然我尝试过但它不起作用 这很糟糕 因为然后我必须经历 NSNumber numberWithInt someIn
  • 将数据从子模态 VC 传递到父视图控制器的最佳方法?

    将数据从子模式视图传递到父视图控制器的最佳方法是什么 我的 iPad 应用程序上有一个子模式登录屏幕 我想将用户信息传回父级分割视图控制器 我正在考虑使用 NSNotification 但我不确定这是否是将数据传递回父级的最简单 最有效的方
  • 动态更新 UIAlertView 消息和换行符问题

    我需要在 UIAlertView 的消息中显示多行文本 我尝试过添加 n 但没有效果 它仍然显示 这是一个示例 但是 如果我将 iPhone 切换为横向模式 它会按照我的预期显示该消息 然后 如果我切换回纵向模式 它也会正确显示 更新 经过
  • Xcode 6 Save for Enterprise Deployment 不再为 ipa 创建 plist?

    Xcode 5 帮助为企业 ipa 创建 plist 描述符 Xcode 6 6A313 仅创建 ipa 这是错误还是有意更改 如果是这样 退后一步的原因是什么 如果我之前没有使用 Xcode 5 生成 plist 我需要自己手动构建它 您
  • Swift 无法从上到下呈现视图控制器

    在我的应用程序中 我必须从上到下呈现屏幕 我尝试了下面的代码 它给出了相同的正常呈现风格 let screen self storyboard instantiateViewController withIdentifier Screen1
  • 自定义 UIPopoverController 视图背景和边框颜色

    是否可以更改弹出视图的边框颜色 导航栏样式 颜色和箭头样式 颜色 如果是这样 怎么办 如果有一些示例代码可用 那就太好了 iOS 7以上 可以更改backgroundColor of UIPopoverController这会影响导航背景颜
  • 如何在iOS8自定义键盘上方添加工具栏?

    My problem is write picture I really need you help Maybe inputAccessoryView inputAccessoryViwController can be used but
  • 使用 CLPlacemark、administrativeArea、iOS6/iOS7 更改内容

    我计划为 ios 7 制作一个应用程序 并且有管理区域地标属性的问题 对于 iOS6 我得到行政区域的全名 例如 加利福尼亚 但对于 iOS7 我得到 CA 的值 当情况如此变化时 这是一个问题 有什么方法可以控制这个输入 使其更加一致吗
  • 新的 iTunes 连接界面错误“您必须选择一个版本”

    当尝试将我的新应用程序提交到应用程序商店时 我注意到苹果已经更改了其网站界面 更新元数据和关键字并点击 提交审核 后 我收到错误 您必须选择一个版本 通过谷歌搜索 我没有找到答案 但是 我注意到 构建 标题旁边有一个加号按钮 您必须在其中选
  • 获取UIButton的UITableViewCell?

    我正在尝试使用UIButton 它位于自定义的UITableViewCell类称为GFHomeCell The GFHomeCell has a postID属性 我想在准备继续时发送该属性 我设置了一个在按下按钮时运行的方法 但是 在按下
  • iOS:接收“304 Not Modified”响应时 AVPlayerItem 中的错误

    这是一个非常奇怪的错误 我有一个 tableView 每个单元格都使用AVPlayer从远程服务器流式传输视频 想象一下类似 Vine 的时间线 因此 当我滚动时 重复使用的单元格会使用新视频重新配置播放器 问题是 如果我非常快地来回滚动
  • NSNotification 与dispatch_get_main_queue

    和 关联这个问题 https stackoverflow com questions 7905192 iphone grand central dispatch main thread我想知道关于何时使用 NSNotification 在主
  • iOS 9.3 出现新的 UIPDFPageRenderOperation 错误?

    我正在向 UIWebView 添加一些 PDF 链接 每次加载并做出滚动手势时 都会收到此错误 objc 910 UIPDFPageRenderOperation 对象 0x14acaca10 过度释放 当已经解除分配时 打断 objc o
  • Quickblox 聊天未进行身份验证

    我在我的应用程序中使用 Quickblox 进行一对一聊天 用户已经登录 但是当我尝试登录聊天时 出现以下错误 2014 03 31 12 42 09 532 MyChat 2175 3803 QBChat didNotAuthentica
  • 快速从 appDelegate 中 popToRootViewController

    我试图从应用程序委托弹出到导航堆栈的根视图控制器 并且在将 obj c 中的内容转换为 swift 时遇到一些问题 obj c 中的工作原理 UINavigationController navigationController UINav
  • 启动时运行后台任务

    我正在编写一个 iOS 应用程序 它使用 Dropbox Datastore API 在多个设备之间同步数据 在 Android 上 我可以告诉服务在启动时启动 这使其能够同步 设备关闭时可能发生的任何更改 我无法找到让我的应用程序在 iO

随机推荐

  • 基于 SpringBoot+vue 的校园二手书平台

    文章目录 1 介绍 2 技术栈 3 需求分析 4系统设计 4 1数据库设计 5系统详细设计 5 1系统功能模块 5 2管理员功能模块 5 3 卖家用户功能模块 6 源码获取 1 介绍 本次设计任务是要设计一个乐校园二手书交易管理系统 通过这
  • chmod修改权限命令

    chmod修改权限命令 在linux系统中 进行命令键入开启文件或文件夹时 常会出现权限不够的报错信息 这里就需要chmod命令来修改权限了 语法为chmod R lt 模式 gt lt 文件或目录 gt 例如 chmod 777 file
  • 蓝云EasyTrack——专业的企业级项目管理工具

    项目管理工作越来越离不开项目管理工具 如果是个人或单个小型团队使用 用来管理任务 可以选择在线的协同工具或轻量项目管理工具 如果是多团队 跨部门项目管理 或者用于企业级的项目管理 那就需要专业的企业级项目管理工具 术业有专攻 在IT 产品研
  • 异常java.lang.NoSuchMethodError: org.apache.poi.ss.usermodel.Sheet.getDrawingPat原因与解决

    在做excel导出时遇到的异常 java lang NoSuchMethodError org apache poi ss usermodel Sheet getDrawingPat 原因是 jar包不兼容 这是依赖
  • 2023华为od机试C++ 目录与考试说明(B卷+A卷)

    本专栏使用C 语言解题 常见问题 1 进入机考网页之后如果链接上写着 B卷 就表示是B卷题库 对应着目录中的时间这一列 2023Q2 在2023年5月10日之后 大多数同学收到的应该是B卷题库 2 2022年的题库已经废弃 如果时间紧迫 建
  • 程序员自曝接私活:10个月时间接了30多个单子,纯收入40万

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 随着互联网的发展 对于程序员的需求也日益增多 一些程序员在按部就班的同时 也会在外接一些私活增加收入 无独有偶 有一名程序员无意间发现了商机 开始了全职接私活 在10个月时
  • oVirt:数据中心的开源虚拟化

    oVirt 数据中心的开源虚拟化 通过标记 发布 2019年1月30日 更新 2019年2月27日 oVirt是基于Linux Libvirt和KVM的完整的开源虚拟化解决方案 它旨在成为VMware vSphere的替代产品 让我们看看它
  • PyTorch深度学习实践概论笔记8练习-kaggle的Titanic数据集预测(一)数据分析

    刘老师在第8讲PyTorch深度学习实践概论笔记8 加载数据集中留下一个练习 对kaggle上的Titanic数据集 使用DataLoader类进行分类 训练目标是预测某位乘客是否活下来 Survived 本篇文章先读取数据和做一些简单的数
  • QT编译安装QtMqtt子模块,WIN平台

    QT安装QtMqtt子模块 下载源代码编译 添加库文件到QT安装目录 测试工程 最终效果 2021 10 15 补充 将配置文件添加到安装目录 完整文件下载 系统 Windows10 环境 QT5 12 9 下载源代码编译 GitHub上下
  • 【Qt Quick】Android环境配置及第一个Hello World

    Android环境配置及第一个Hello World 安装Java jdk 安装Android studio 安装手机模拟器 配置Qt 第一个Hello World 常见错误 安装Java jdk 1 下载 链接 link Java1 8
  • Java数据库开发之Hibernate框架(4)Hibernate的查询

    占位 下周补充
  • kettle定时调度

    简单版 https blog csdn net hzp666 article details 107841754 详细版 1 场景介绍 根据不同的操作系统定时调度kettle资源库中的job 1 1Windows系统的定时调度 我的是 ve
  • 网络IO模型

    网络IO的本质是对socket的读取 在网络IO的过程中 有两个重要角色 分别是系统内核和用户进程 首先要等系统内核准备好数据 然后将数据从系统内核拷贝至用户进程空间 这样才算完成了一次IO 如果在系统内核没有准备好数据时 用户IO线程在此
  • Gimpel Software推出C和C ++的首选静态分析工具 PC-lint Plus,不再维护PC-lint/FlexeLint。

    Gimpel Software已不再维护PC lint FlexeLint版本9 最终更新是2014年发布的版本9 00L Gimpel Software在2018年底之前为PC lint FlexeLint提供技术支持 Gimpel So
  • Qt头文件中的QT_BEGIN_NAMESPACE

    在源代码中是这样定义的 1 define QT BEGIN NAMESPACE namespace QT NAMESPACE 2 define QT END NAMESPACE 也就是说 如果你定义以下内容 1 QT BEGIN NAMES
  • 数据结构-链式队列

    link queue node h ifndef LINK QUEUE NODE H define LINK QUEUE NODE H include
  • 串口通信协议概述——针对面试

    串口通信 串口通信 Serial Communications 的概念非常简单 串口按位 bit 发送和接收字节的通信方式 重要参数 1 数据位 2 停止位 3 奇偶校验位 4 波特率 其中 数据位 停止位 奇偶校验位又是数据格式 数据格式
  • PyWebIo

    Part1什么是 PyWebIo PyWebIO 提供了一系列命令式的交互函数来在浏览器上获取用户输入和进行输出 将浏览器变成了一个 富文本终端 可以用于构建简单的 Web 应用或基于浏览器的 GUI 应用 使用 PyWebIO 开发者能像
  • 数据库项目代码生成工具V1.18.08.18.0(RIO)

    下载 1 第一步 2 第二步 3 第三步 结果
  • ios10.3之CoreData的详细教程

    首先如果要使用CoreData可以选择在初创项目时选择添加coredata 也可以选择自己添加coredata文件 系统添加coredata后会在Appdelegate类中自动添加一个persistentContainer属性 和一个sav