更好的世界:用定制托管对象上下文(NSManagedObjectContext)防止产生“空白”托管对象(下)

在这里插入图片描述

概述

用 SwiftUI + CoreData 这对“双剑合璧”的强力开发组合,我们可以事倍功半、非常 easy 的开发出界面元素丰富且背后拥有持久数据库支持的 App。

在这里插入图片描述

不过,在某些情况下它们被误用或错用也可能带来一些“藏形匿影”的顽疾。

在本篇博文中,您将学到如下内容:

  • 概述
  • 4. “神兵天降”:自定义托管对象上下文(Custom NSManagedObjectContext)
  • 5. “诡异”消失的上下文!
  • 总结

相信学完本课后,大家一定会对自定义托管对象上下文(NSManagedObjectContext)的理解更加纯熟和精进!

那还等什么呢?Let‘s go!!!😉


4. “神兵天降”:自定义托管对象上下文(Custom NSManagedObjectContext)

熟悉 CoreData 框架组织架构的小伙伴们都知道,要想恣意操作内存中的托管对象,我们必须借助于托管对象上下文(NSManagedObjectContext)来达成。

在这里插入图片描述

在一般情况下,CoreData 运行时(Runtime)会为我创建默认的托管对象上下文。在大多数场景下用它就足够了。不过,在某些情况下我们可以创建自己的托管对象上下文,比如后台数据操作、撤销数据的保存或修改以及对持久存储的细粒度控制等。

在这里,利用特殊定制的 NSManagedObjectContext 对象恰巧可以帮我们“排忧解难”。

我们的思路很简单:以实际工作的托管对象上下文为父对象(Root),创建一个新的托管对象上下文(Custom)。这样的话,所有插入 Custom 上下文的 Worry 托管对象都必须再用 Root 上下文保存才可以真正存储到内存和数据库中。

struct NewWorryView: View {
    @ObservedObject private var newWorry: Worry
    
    init() {
        let context = Common.moc_auto
        let tmpContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        tmpContext.parent = context
        // 将新建的 Worry 对象插入到自定义托管对象上下文(tmpContext)而不是父上下文(context)中
        newWorry = Worry.new(tmpContext)
    }
}

对于实际的保存操作,我们需要“双重” Save:

Button("保存") {
    guard let tmpContext = newWorry.managedObjectContext, let parentContext = tmpContext.parent else { return }
    guard verify() else { return }
    
    // “双重”保存
    try! tmpContext.save()
    try! parentContext.save()
    
    dismissor()
}

如此这般,我们就成功避免了“空白” Worry 对象的产生:

在这里插入图片描述

虽然我们现在搞定了“空白”托管对象“野蛮繁殖”的问题,不过还有一个隐藏的 bug 急需解决。


更多关于 CoreData 开发相关知识的介绍,请小伙伴们移步如下链接观赏精彩的博文:

  • 『第十一章』数据持久化:CoreData 与 CloudKit
  • 漫谈初学者处理 CoreData 数据之启示录
  • 探究 CoreData 使用索引(Index)机制加速查表究竟如何实现?
  • iOS 16 中 CoreData 托管对象发生变化但其衍生 (Derived) 属性在 SwiftUI 中不刷新的解决
  • 何时Xcode中CoreData托管对象Optional和Default Value选项会变得尤为敏感?

5. “诡异”消失的上下文!

上面,我们圆满解决了“空白” Worry 对象的问题,不过通过实际运行可以发现,当我们试图保存新建的 Worry 托管对象时,却无法完成保存操作:

在这里插入图片描述

这又是为什么呢?

问题就出在我们刚才创建的自定义托管对象上下文上!

回到我们前面新建 Worry 对象的保存方法上,可以看到当用户点击保存按钮时,我们实际从 newWorry 对象的 managedObjectContext 属性获取到的上下文竟然为 nil。

Button("保存") {
	// tmpContext 为 nil,导致 guard 语句直接退出
    guard let tmpContext = newWorry.managedObjectContext, let parentContext = tmpContext.parent else { return }
    guard verify() else { return }
    
    // “双重”保存
    try! tmpContext.save()
    try! parentContext.save()
    
    dismissor()
}

在 OC ARC 背后支持的 Swift 运行时里,要想一个对象实例驻留于内存中,至少要保证它被一个强引用(Strong Reference)所“套牢”。

回忆一下:我们之前创建的自定义 tmpContext 上下文,在 init() 方法结束时就会“灰飞烟灭”。虽然我们的 newWorry 托管对象引用了它,但它们只是弱引用(Weak Reference)的关系(即托管对象对其上下文的引用是 weak 引用类型),无奈不顶用啊。

知道了问题的症结,解决起来就很简单了。我们只需要确保自定义托管对象上下文被一个强引用“牢牢抓住”即可,这可以通过在视图层面创建它来完成:

struct V3_NewWorryView: View {
    @ObservedObject private var newWorry: Worry
    // 托管对象中的上下文是弱引用,如果不在下面将其保存则其会立即“丢失”
    private let tmpContext: NSManagedObjectContext
}

最后我们运行代码,可以看到新建的 Worry 对象已经可以被稳妥的存储啦:

在这里插入图片描述

至此,我们在一个“鸟语花香、山清水秀”的“新世界”,利用自定义托管对象上下文完美的解决了博客开头引出的问题,棒棒哒!💯

总结

在本篇博文中,我们进一步讨论了如何用自定义托管对象上下文(NSManagedObjectContext)来消除 SwiftUI 视图中冗余的“空白”对象,并顺面解决了上下文“诡异”消失的问题。

感谢观赏,再会啦!😎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/952490.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

个人在技术领导力方面的自我反思与提升

大家好!我是 [数擎 AI],一位热爱探索新技术的前端开发者,在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情,欢迎关注我的文章,我们一起成长、进步! 开发领域:前端开发 | A…

Win10本地部署大语言模型ChatGLM2-6B

鸣谢《ChatGLM2-6B|开源本地化语言模型》作者PhiltreX 作者显卡为英伟达4060 安装程序 打开CMD命令行,在D盘新建目录openai.wiki if not exist D:\openai.wiki mkdir D:\openai.wiki 强制切换工作路径为D盘的openai.wiki文件夹。 cd /d D:\openai.wik…

排列高手

这篇主要是求再排位为 {1&#xff0c;3&#xff0c;4&#xff0c;....&#xff0c;n&#xff0c;2}的最优顺序下求mex。 但不知道为什么这样是最优 子数列的个数公式&#xff1a; 对于一个长度为N的数组&#xff0c; #include <bits/stdc.h> using namespace std; lon…

公众号如何通过openid获取unionid

通过接口 https://api.weixin.qq.com/cgi-bin/user/info?access_tokenxxxxxxx&langzh_CN 返回的数据如下&#xff1a; 前提是必须绑定 微信开放平台 token如何获取呢 代码如下&#xff1a; String tokenUrl "https://api.weixin.qq.com/cgi-bin/token"; …

软件测试预备知识④—NTFS权限管理、磁盘配额与文件共享

在软件测试的实际环境搭建与管理过程中&#xff0c;了解和掌握NTFS权限管理、磁盘配额以及文件共享等知识至关重要。这些功能不仅影响系统的安全性和稳定性&#xff0c;还对测试数据的存储、访问以及多用户协作测试有着深远的影响。 一、NTFS权限管理 1.1 NTFS简介 NTFS&am…

类结构——构造方法

类结构——构造方法 构造方法的基本特性默认构造方法构造方法重载使用this关键字私有构造方法总结 构造方法&#xff08;Constructor&#xff09;是Java编程语言中的一个重要概念&#xff0c;用于初始化新创建的对象。在对象实例化时被调用&#xff0c;并负责设置对象的初始状态…

【linux系统之redis6】redis的安装与初始化

下载redis的linux对应的安装包&#xff0c;并上传到linux虚拟机里面 解压压缩包 tar -zxzf redis-6.2.6.tar.gz解压后&#xff0c;进入redis文件 cd redis-6.2.6执行编译 make && make install看到下图&#xff0c;就说明redis安装成功了 默认的安装路径&#xff0c…

STM32-笔记40-BKP(备份寄存器)

一、什么是BKP&#xff08;备份寄存器&#xff09;&#xff1f; 备份寄存器是42个16位的寄存器&#xff0c;可用来存储84个字节的用户应用程序数据。他们处在备份域里&#xff0c;当VDD电源被切断&#xff0c;他们仍然由VBAT维持供电。当系统在待机模式下被唤醒&#xff0c;或…

MobaXterm界面的简单介绍

界面全局 “命令行界面”&#xff08;Command Line Interface&#xff0c;简称CLI&#xff09;或“终端”&#xff08;Terminal&#xff09; 在这个界面中&#xff0c;用户可以输入命令来与操作系统进行交互,灰色光标是输入命令的位置 标签栏&#xff08;Tab Bar&#xff09; …

有收到腾讯委托律师事务所向AppStore投诉带有【水印相机】主标题名称App的开发者吗

近期&#xff0c;有多名开发者反馈&#xff0c;收到来自腾讯科技 (深圳) 有限公司委托北京的一家**诚律师事务所卞&#xff0c;写给AppStore的投诉邮件。 邮件内容主要说的是&#xff0c;腾讯注册了【水印相机】这四个字的商标&#xff0c;所以你们这些在AppStore上的app&…

UI自动化测试保姆级教程①

欢迎来到阿妮莫的学习小屋慢也好&#xff0c;步子小也好&#xff0c;在往前走就好 目录 自动化测试 简介 作用 分类 优缺点 优点 缺点(误区) UI自动化测试 自动化测试使用场景 自动化测试实现时间 Selenium框架 特点 Web自动化测试环境部署 Selenium包安装 浏览…

Linux 下信号的保存和处理

信号的几个状态 信号抵达: 当接收到的信号被处理时, 此时就成为信号的抵达信号的未决: 从信号的产生到信号抵达这个时间段之间, 称为信号未决信号阻塞: 当进程设置了某个信号为阻塞后, 这个进程就不会在接收到这个信号信号忽略: 将信号设置为忽略后, 接收到这个信号, 对这个信…

IntelliJ IDEA中Maven项目的配置、创建与导入全攻略

大家好&#xff0c;我是袁庭新。 IntelliJ IDEA是当前最流行的Java IDE&#xff08;集成开发环境&#xff09;之一&#xff0c;也是业界公认最好用的Java开发工具之一。IntelliJ IDEA支持Maven的全部功能&#xff0c;通过它我们可以很轻松地实现创建Maven项目、导入Maven项目、…

深度学习笔记11-优化器对比实验(Tensorflow)

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目录 一、导入数据并检查 二、配置数据集 三、数据可视化 四、构建模型 五、训练模型 六、模型对比评估 七、总结 一、导入数据并检查 import pathlib,…

JavaEE之定时器及自我实现

在生活当中&#xff0c;有很多事情&#xff0c;我们不是立马就去做&#xff0c;而是在规定了时间之后&#xff0c;在到该时间时&#xff0c;再去执行&#xff0c;比如&#xff1a;闹钟、定时关机等等&#xff0c;在程序的世界中&#xff0c;有些代码也不是立刻执行&#xff0c;…

Qt学习笔记第81到90讲

第81讲 串口调试助手实现自动发送 为这个名叫“定时发送”的QCheckBox编写槽函数。 想要做出定时发送的效果&#xff0c;必须引入QT框架下的毫秒级定时器QTimer&#xff0c;查阅手册了解详情。 在widget.h内添加新的私有成员变量&#xff1a; QTimer *timer; 在widget类的构造…

【LeetCode】力扣刷题热题100道(16-20题)附源码 容器 子数组 数组 连续序列 三数之和(C++)

目录 1.盛最多水的容器 2.和为K的子数组 3.最大子数组和 4.最长连续序列 5.三数之和 1.盛最多水的容器 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴…

AI多模态技术介绍:视觉语言模型(VLMs)指南

本文作者&#xff1a;AIGCmagic社区 刘一手 AI多模态全栈学习路线 在本文中&#xff0c;我们将探讨用于开发视觉语言模型&#xff08;Vision Language Models&#xff0c;以下简称VLMs&#xff09;的架构、评估策略和主流数据集&#xff0c;以及该领域的关键挑战和未来趋势。通…

jenkins入门13--pipeline

Jenkins-pipeline(1)-基础 为什么要使用pipeline 代码&#xff1a;pipeline 以代码的形式实现&#xff0c;通过被捡入源代码控制&#xff0c; 使团队能够编译&#xff0c;审查和迭代其cd流程 可连续性&#xff1a;jenkins 重启 或者中断后都不会影响pipeline job 停顿&#x…

【线性代数】通俗理解特征向量与特征值

这一块在线性代数中属于重点且较难理解的内容&#xff0c;下面仅个人学习过程中的体会&#xff0c;错误之处欢迎指出&#xff0c;有更简洁易懂的理解方式也欢迎留言学习。 文章目录 概念计算几何直观理解意义PS.适用 概念 矩阵本身就是一个线性变换&#xff0c;对一个空间中的…