SwiftUI 在 Xcode 预览修改视图 FetchedResults 对象的属性时为什么会崩溃?

在这里插入图片描述

概览

从 SwiftUI 诞生那天起,让秃头码农们又爱又恨的 Xcode 预览就在界面调试中扮演了及其重要的角色。不过,就是这位撸码中的绝对主角却尝尝在关键时刻“掉链子”。

在这里插入图片描述

比如当修改 SwiftUI 视图中 FetchedResults 对象的属性时,Xcode 预览可能会毫不留情的发生崩溃。这是怎么回事,又该如何解决呢?

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

  • 概览
  • 1. 莫名其妙的崩溃场景
  • 2. 崩溃的根本原因
  • 总结

本篇博文代码测试环境:macOS 15.2 + Xcode 16.1

相信学完本课后,小伙伴们对于 Xcode 预览中 SwiftUI 视图 FetchedResults 对象的领悟又会更加精进一层!

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


1. 莫名其妙的崩溃场景

在 SwiftUI 与 CoreData 共同协作的视图中,我们常常需要使用 @FetchRequest 属性包装器来获取所有相关的托管对象:

struct MainTest: View {    
    @FetchRequest(sortDescriptors: [.init(keyPath: \WorryObject.name, ascending: false)], animation: .bouncy) var allWorryObjects: FetchedResults<WorryObject>
    
    @State var ascending = false
    
    var body: some View {
        NavigationStack {
            List {
                ForEach(allWorryObjects) { wObj in
                    VStack(alignment: .leading) {
                        Label(wObj.name ?? "", systemImage: "brain.filled.head.profile")
                            .font(.title2)
                        Text(wObj.desc ?? "")
                            .foregroundStyle(.gray)
                    }
                }
            }
            .toolbar {
                ToolbarItem(placement: .topBarLeading) {
                    Button(ascending ? "升序" : "降序") {
                        ascending.toggle()
                    }
                }
            }
            .onChange(of: ascending) {_,new in
                allWorryObjects.nsSortDescriptors = [.init(keyPath: \WorryObject.name, ascending: ascending)]
            }
        }
    }
}

#Preview {
    let context = Common.moc_auto

    MainTest()
        .task {
            try! WorryObject.createDefaults(context)
        }
}

我们在上面的代码中主要做了这样几件事:

  • 使用 @FetchRequest 属性包装器产生结果为 FetchedResults<WorryObject> 的托管对象集合;
  • 遍历每个 WorryObject 对象并在视图中显示它们;
  • 让用户通过 ascending 状态切换 allWorryObjects 集合的排序方式,这是利用动态修改 FetchedResults<WorryObject> 的 nsSortDescriptors 属性来实现的;

不过,上面这段代码在 Xcode 预览中会有两个问题:

  1. 我们的 WorryObject.createDefaults() 方法明明产生了若干默认 WorryObject 对象,但在预览视图中却依旧是一片“空白”;
  2. 当我们切换 allWorryObjects 集合的排序方式时,预览会立即崩溃;

在这里插入图片描述

从预览崩溃栈中我们可以发现,崩溃的原因是重新设置 FetchedResults<WorryObject> 对象的 nsSortDescriptors 属性的操作所导致的:

在这里插入图片描述

然而奇怪的是,完全相同的代码在模拟器和真机上却毫无任何问题:

在这里插入图片描述

为什么单单 Xcode 预览会如此蛋疼呢?

2. 崩溃的根本原因

其实 Xcode Preview 榱崩栋折的原因很简单,我们也在之前很多篇博文详细讨论过了。

简单来说,在 Xcode 预览环境中 SwiftUI 视图若包含 @FetchRequest 属性包装器,则必须向视图传递正确的 managedObjectContext 环境变量。而且该环境变量必须特别针对预览做出修正。


关于在 Xcode 预览中向 SwiftUI 视图传递 managedObjectContext 环境变量导致的其它问题,请小伙伴们移步如下链接观赏进一步精彩的内容:

  • 向 SwiftUI 视图注入 managedObjectContext 环境变量导致 Xcode 预览(Preview)崩溃的解决
  • SwiftUI 视图 CoreData 的 @FetchRequest 请求结果在预览中无法自动刷新的解决之道

按照这种思路,我们可以很快写出修复方案:

struct MainTest: View {
    
    @Environment(\.managedObjectContext) var context
    @FetchRequest(sortDescriptors: [.init(keyPath: \WorryObject.name, ascending: false)], animation: .bouncy) var allWorryObjects: FetchedResults<WorryObject>
}

#Preview {
    let context = try! Common.moc_auto.cook4Preview(WorryObject.self)
    
    MainTest()
        .environment(\.managedObjectContext, context)
        .task {
            // 创建默认 WorryObject 对象集合
            try! WorryObject.createDefaults(context)
        }
}

在上面的代码中,我们向 MainTest 视图传递了修复后的托管对象上下文,这使得它在 Xcode 预览环境中表现的出类拔萃!棒棒哒!💯

在这里插入图片描述

至此,我们已经彻底了解了博文开头那个问题,并一发入魂给出完美的解决方案!么么哒!


想要进一步系统地学习 Swift 开发的小伙伴们,可以来我的《Swift 语言开发精讲》专栏逛一逛哦:

在这里插入图片描述

  • 《Swift 语言开发精讲》

总结

在本篇博文中,我们讨论了为何包含 FetchedResults 对象的 SwiftUI 视图属性被修改时,在 Xcode 预览中会导致崩溃。并在最后给出完美解决之道。

感谢观赏,再会啦!😎

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

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

相关文章

【字节青训营-7】:初探 Kitex 字节微服务框架(使用ETCD进行服务注册与发现)

本文目录 一、Kitex概述二、第一个Kitex应用三、IDL四、服务注册与发现 一、Kitex概述 长话短说&#xff0c;就是字节跳动内部的 Golang 微服务 RPC 框架&#xff0c;具有高性能、强可扩展的特点&#xff0c;在字节内部已广泛使用。 如果对微服务性能有要求&#xff0c;又希望…

51单片机入门_05_LED闪烁(常用的延时方法:软件延时、定时器延时;while循环;unsigned char 可以表示的数字是0~255)

本篇介绍编程实现LED灯闪烁&#xff0c;需要学到一些新的C语言知识。由于单片机执行的速度是非常快的&#xff0c;如果不进行延时的话&#xff0c;人眼是无法识别(停留时间要大于20ms)出LED灯是否在闪烁所以需要学习如何实现软件延时。另外IO口与一个字节位的数据对应关系。 文…

JVM的GC详解

获取GC日志方式大抵有两种 第一种就是设定JVM参数在程序启动时查看&#xff0c;具体的命令参数为: -XX:PrintGCDetails # 打印GC日志 -XX:PrintGCTimeStamps # 打印每一次触发GC时发生的时间第二种则是在服务器上监控:使用jstat查看,如下所示&#xff0c;命令格式为jstat -gc…

基于python去除知乎图片水印

基于python去除知乎图片水印 背景&#xff1a;看到知乎技术文章里面的图片非常好&#xff0c;但是下载下来都是带有水印的&#xff0c;并不是不尊重别人的版权和劳动成果&#xff0c;纯粹的是洁癖&#xff0c;总感觉水印打上去很难受~~~ 实在想去掉水印&#xff0c;但是又不会P…

Android学习20 -- 手搓App2(Gradle)

1 前言 昨天写了一个完全手搓的&#xff1a;Android学习19 -- 手搓App-CSDN博客 后面谷歌说不要用aapt&#xff0c;d8这些来搞。其实不想弄Gradle的&#xff0c;不过想着既然开始了&#xff0c;就多看一些。之前写过一篇Gradle&#xff0c;不过是最简单的编译&#xff0c;不涉…

【愚公系列】《循序渐进Vue.js 3.x前端开发实践》051-案例:教务系统学生列表页面

标题详情作者简介愚公搬代码头衔华为云特约编辑&#xff0c;华为云云享专家&#xff0c;华为开发者专家&#xff0c;华为产品云测专家&#xff0c;CSDN博客专家&#xff0c;CSDN商业化专家&#xff0c;阿里云专家博主&#xff0c;阿里云签约作者&#xff0c;腾讯云优秀博主&…

毕业设计:基于深度学习的高压线周边障碍物自动识别与监测系统

目录 前言 课题背景和意义 实现技术思路 一、算法理论基础 1.1 卷积神经网络 1.2 目标检测算法 1.3 注意力机制 二、 数据集 2.1 数据采集 2.2 数据标注 三、实验及结果分析 3.1 实验环境搭建 3.2 模型训练 3.2 结果分析 最后 前言 &#x1f4c5;大四是整个大学…

2025.2.1——八、Web_php_wrong_nginx_config

题目来源&#xff1a;攻防世界 Web_php_wrong_nginx_config 目录 一、打开靶机&#xff0c;整理信息 二、解题思路 step 1&#xff1a;找找解题入口 step 2&#xff1a;抓包修改信息&#xff0c;得到配置文件 step 3&#xff1a;找到突破口&#xff0c;进行文件遍历 st…

Netty中用了哪些设计模式?

大家好&#xff0c;我是锋哥。今天分享关于【Netty中用了哪些设计模式&#xff1f;】面试题。希望对大家有帮助&#xff1b; Netty中用了哪些设计模式&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Netty 是一个基于 Java 的高性能网络应用框架&#…

【办公类-99-01】20250201学具PDF打印会缩小一圈——解决办法:换一个PDF阅读器

背景需求&#xff1a; 2024年1月13日&#xff0c;快要放寒假了&#xff0c;组长拿着我们班的打印好的一叠教案来调整。 “前面周计划下面的家园共育有调整&#xff0c;你自己看批注。” “还有你这个教案部分的模版有问题&#xff0c;太小&#xff08;窄&#xff09;了。考虑…

【BUUCTF杂项题】FLAG

一.FLAG 一张图片扔进随波逐流 发现RGB似乎隐藏压缩包 优先考虑RBG中的LSB隐写&#xff0c;用Stegsolve打开文件 1.查看每个颜色通道下的图片&#xff0c;未发现异常 2.LSB最低位提取&#xff0c;用Stegsolve的Data Extrace功能&#xff0c;确实存在一个压缩包&#xff0c;sa…

ros 创建Node

1、使用catkin_create_pkg创建一个软件包 catkin_create_pkg ssr_pkg roscpp rospy std_msgs 2、在软件包的src文件夹下创建一个节点的cpp源码文件 3、在CMakeLists.txt中设置节点源码的编译规则 4.编译运行 编译&#xff1a;shiftctrlB 运行&#xff1a; rosrun ssr_pkg …

给AI用工具的能力——Agent

ReAct框架&#xff1a; Reason Action&#xff0c;推理与行动结合 可以借助思维链&#xff0c;用小样本提示展示给模型一个ReAct框架 推理&#xff1a;针对问题或上一步观察的思考 行动&#xff1a;基于推理&#xff0c;与外部环境的一些交互&#xff08;调用外部工具&…

实验十 Servlet(一)

实验十 Servlet(一) 【实验目的】 1&#xff0e;了解Servlet运行原理 2&#xff0e;掌握Servlet实现方式 【实验内容】 1、参考课堂例子&#xff0c;客户端通过login.jsp发出登录请求&#xff0c;请求提交到loginServlet处理。如果用户名和密码相同则视为登录成功&#xff0c…

PAT甲级1052、Linked LIst Sorting

题目 A linked list consists of a series of structures, which are not necessarily adjacent in memory. We assume that each structure contains an integer key and a Next pointer to the next structure. Now given a linked list, you are supposed to sort the stru…

【BUUCTF杂项题】荷兰宽带数据泄露、九连环

一.荷兰宽带数据泄露 打开发现是一个.bin为后缀的二进制文件&#xff0c;因为提示宽带数据泄露&#xff0c;考虑是宽带路由器方向的隐写 补充&#xff1a;大多数现代路由器都可以让您备份一个文件路由器的配置文件&#xff0c;软件RouterPassView可以读取这个路由配置文件。 用…

【Game】Powerful——The Dragon Hiding in Deep Waters(3)

文章目录 1、规则2、条件——宠物2.1、宠物装备2.1、宠物突破2.2、洗练石 3、条件——符石4、条件——化龙鼎5、附录——星穹 1、规则 寒渊城&#xff0c;神秘老兵处可查看 霜风携雨掠寒江&#xff0c;孤城独影人心凉 贤才此件难相遇&#xff0c;忠骨何日还故乡 宠物、符石、…

差分数组的学习

文章目录 1.差分数组的应用场景2.如何构造一个差分数组2.1 原数组转换为差分数组2.2 差分数组还原为原数组 3.差分数组的特性 1.差分数组的应用场景 需要频繁对某个区间的数组进行增减操作 2.如何构造一个差分数组 2.1 原数组转换为差分数组 # 存在一个数组Nums,求出他的差分…

AES 与 SM4 加密算法:深度解析与对比

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

【C++】线程池实现

目录 一、线程池简介线程池的核心组件实现步骤 二、C11实现线程池源码 三、线程池源码解析1. 成员变量2. 构造函数2.1 线程初始化2.2 工作线程逻辑 3. 任务提交(enqueue方法)3.1 方法签名3.2 任务封装3.3 任务入队 4. 析构函数4.1 停机控制 5. 关键技术点解析5.1 完美转发实现5…