当前位置: 首页 > java >正文

一场陟遐自迩的 SwiftUI + CoreData 性能优化之旅(上)

在这里插入图片描述

概述

自从 SwiftUI 诞生那天起,我们秃头码农们就仿佛打开了一个全新的撸码世界,再辅以 CoreData 框架的鼎力相助,打造一款持久存储支持的 App 就像探囊取物般的 Easy。

在这里插入图片描述

话虽如此,不过 CoreData 虽好,稍不留神也可能会让代码执行速度“蜗行牛步”,这该如何解决呢?

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

  • 概述
  • 1. 当前源代码执行的“小瓶颈”
  • 总结

这是两篇偏向撸码的博文,里面有较多的源代码展示,我们会循序渐进地完成整个优化目标,希望大家能够喜欢。

那还等什么呢?让我们马上开始 CoreData 优化大冒险吧!
Let’s go!!!😉


1. 当前源代码执行的“小瓶颈”

要想小试拳脚,我们必须先有需要优化的代码。下面我就满足大家吧:

struct MonthCountsView: View {@Environment(\.managedObjectContext) var contextlet counter: ProjectCounterlet year: Intlet month: Int@State private var isShowMonthCountsChart = falsevar body: some View {// #1let daysCounts = try! counter.queryDaysCounts(year: year, month: month, context: context)// #2let days = daysCounts.keys.sorted(using: SortDescriptor(\.self, order: .reverse))VStack {Button(isShowMonthCountsChart ? "月计数" : "月计数图表") {withAnimation(.bouncy) {isShowMonthCountsChart.toggle()}}.frame(maxWidth: .infinity, alignment: .leading)if isShowMonthCountsChart {MonthCountsChart(counter: counter, daysCountsDict: daysCounts).frame(minHeight: 200)} else {LazyVGrid(columns: [GridItem](repeating: .init(.adaptive(minimum: 100, maximum: 120), spacing: 8), count: 4)) {ForEach(days, id: \.self) { day inlet dayCounts = daysCounts[day]!let totalCount = dayCounts.totalCountNavigationLink {List {LabeledContent("当日总计数") {Text("\(totalCount)\(counter.unit ?? "")").font(.title2).foregroundStyle(counter.nature.data.color)}Section("单次计数") {if let counts = dayCounts.counts {ForEach(counts, id: \.time) { trace inHStack {Text(Common.timeHHmmFt.string(from: trace.time)).monospacedDigit()Spacer()Text("\(trace.count)\(counter.unit ?? "")").font(.title3).foregroundStyle(counter.nature.data.color)}}}}}.listStyle(.plain).navigationTitle(Common.onlyDateFt.string(from: dayCounts.date))} label: {VStack {HStack {Text("\(Common.tinyDateFt.string(from: dayCounts.date))日").font(.headline).frame(maxWidth: .infinity, alignment: .leading)}.padding(.leading).frame(minHeight: 50)Text("\(totalCount)\(Text("\(counter.unit ?? "")").font(.subheadline))").font(.title).padding(.bottom)}.foregroundStyle(.white).monospacedDigit().background(counter.nature.data.color.gradient.opacity(0.88), in: RoundedRectangle(cornerRadius: 10))}}}}}}
}

上面的代码虽然有点冗长,但本质上却很简单。我们主要做了以下几件事:

  • 使用 isShowMonthCountsChart 状态切换月计数图表和 Grid 显示;
  • 在 #1 代码处,我们调用计数器的 queryDaysCounts 方法,来获取指定月的计数记录,返回的结果是一个 [Int: DayCountsData] 字典;
  • 在 #2 代码处,我们将上述字典所有键反向排序并生成所有日的数组,这会将最近的日排在最前面;

为了进一步便于还未秃小码农们的理解,我们下面将缺失的、与计数相关的数据结构一并贴出来:

struct YearCountsData: Identifiable {var id: String {"\(year)"}let year: Intvar totalCount: Int = 0var monthlyAvg: Float = 0.0var monthsCounts: [Int: MonthCountsData]?var monthsCountSortedAry: [MonthCountsData]? {if let data = monthsCounts {let sortedKeys = data.keys.sorted(using: SortDescriptor(\.self, order: .reverse))return sortedKeys.map { data[$0]! }}return nil}}struct MonthCountsData: Identifiable {var id: String {"\(year).\(month)"}let year: Intlet month: Intvar totalCount: Int = 0var daylyAvg: Float = 0.0var daysCounts: [Int: DayCountsData]?var daysCountSortedAry: [DayCountsData]? {if let data = daysCounts {let sortedKeys = data.keys.sorted(using: SortDescriptor(\.self, order: .reverse))return sortedKeys.map { data[$0]! }}return nil}}struct DayCountsData: Identifiable {var id: Date {date}let date: Datevar totalCount: Int = 0var counts: [(time: Date, count: Int)]?}

如您所见,上面 MonthCountsView 视图的问题在于:每次重新渲染(Rendering)它的 body 内容时,我们都会重新计算 daysCounts 字典的内容(而且这是在主线程中完成的),这无疑有些庸人自扰。

那么,我们该如何进一步优化它的执行效率呢?这看似有些一筹莫展。

别急,在下一篇博文中,我们将会一步步“聚沙成塔”,最终完成整个优化目标,期待吧!


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

在这里插入图片描述

  • 《Swift 语言开发精讲》

总结

在本篇博文中,我们介绍了 SwiftUI + CoreData 代码在执行时遇到的一个效率瓶颈,并给出了问题相关的详细源代码。

感谢观赏,我们下一篇再见吧!😎

http://www.xdnf.cn/news/3601.html

相关文章:

  • Redis总结及设置营业状态案例
  • 泰迪杯特等奖案例学习资料:基于CLIP模型微调与知识蒸馏的多模态图文检索系统设计
  • B站Michale_ee——ESP32_IDF SDK——FreeRTOS_7 流数据缓冲区、消息缓冲区
  • Python基于深度学习的网络舆情分析系统(附源码,部署)
  • 基于蒙特卡洛模拟的电路容差分析与设计优化
  • 倒排索引与数据库索引
  • 拆解一个550-800Mhz的LC滤波器内部大图配测试曲线
  • 这款软件的第三方评测:功能、易用性与性能表现如何?
  • 链表系列一> K 个一组翻转链表
  • wsl安装
  • 自动化测试项目2 --- 比特纵横 [软件测试实战 Java 篇]
  • 泰迪杯特等奖案例学习资料:基于时空图卷积网络的结构健康监测数据异常识别系统
  • OrbitControls
  • 【学习笔记】第十章:序列建模:递归神经网络(RNN)
  • k9s 一个基于终端的 Kubernetes 集群管理工具(TUI)
  • Python 数据智能实战 (8):基于LLM的个性化营销文案
  • Redis基本使用
  • 线程池实现
  • 03 - spring security自定义登出页面
  • 学习c语言的第16天
  • 用c 编写的笔记搜索程序
  • 每天学一个 Linux 命令(33):uniq
  • DarkGS:论文解读与全流程环境配置及数据集测试【基于Ubuntu20.04 】【2025最新实战无坑版!!】
  • Linux工作台文件操作命令全流程解析
  • mescroll.js 是在 H5端 运行的下拉刷新和上拉加载插件
  • 网络编程——Socket 编程详解(TCP / UDP)
  • C++拷贝构造函数详解
  • 使用 Mermaid 在 Markdown 中绘制图表
  • 数字智慧方案6213丨智慧园区规划方案(63页PPT)(文末有下载方式)
  • AI大模型-解决开发环境配置不足问题