Swift数据结构库优化可识别元素集合管理
swift-identified-collections库为Swift开发者提供高性能数据结构,用于管理唯一标识元素集合。它解决了普通数组处理可识别元素的性能和稳定性问题。核心组件IdentifiedArray结合了OrderedDictionary的优势,提供了更易用的API。该库适用于SwiftUI应用和Composable Architecture框架开发,提高了代码效率和可靠性。
一个用于以人体工程学和高性能方式处理可识别元素集合的数据结构库。
在为应用程序的状态建模集合元素时,很容易想到使用标准的Array
。然而,随着应用程序变得更加复杂,这种方法可能会在多个方面出现问题,包括意外对错误的元素进行修改,甚至导致崩溃。😬
例如,如果你正在使用SwiftUI构建一个"待办事项"应用程序,你可能会将单个待办事项建模为一个可识别的值类型:
struct Todo: Identifiable { var description = "" let id: UUID var isComplete = false }
然后你会在应用程序的视图模型中将这些待办事项的数组作为已发布的字段持有:
class TodosViewModel: ObservableObject { @Published var todos: [Todo] = [] }
视图可以非常简单地渲染这些待办事项的列表,而且由于它们是可识别的,我们甚至可以省略List
的id
参数:
struct TodosView: View { @ObservedObject var viewModel: TodosViewModel var body: some View { List(self.viewModel.todos) { todo in ... } } }
如果你的部署目标设置为最新版本的SwiftUI,你可能会尝试将绑定传递给列表,以便每一行都可以对其待办事项进行可变访问。这对于简单的情况来说是可行的,但一旦你引入副作用(如API客户端或分析),或者想要编写单元测试,你就必须将这个逻辑推送到视图模型中。这意味着每一行都必须能够将其操作传回视图模型。
你可以通过在视图模型中引入一些端点来实现这一点,比如当一行的完成状态切换时:
class TodosViewModel: ObservableObject { ... func todoCheckboxToggled(at id: Todo.ID) { guard let index = self.todos.firstIndex(where: { $0.id == id }) else { return } self.todos[index].isComplete.toggle() // TODO: 使用API客户端在后端更新待办事项 } }
这段 代码足够简单,但它可能需要对数组进行完整的遍历才能完成任务。
也许让一行将其索引传回视图模型会更高效,然后它可以通过索引直接修改待办事项。但这会使视图变得更复杂:
List(self.viewModel.todos.enumerated(), id: \.element.id) { index, todo in ... }
这还不算太糟,但目前它甚至无法编译。一个演进提案可能很快会改变这一点,但在此之前,List
和ForEach
必须传递一个RandomAccessCollection
,这可能最简单的方法是构造另一个数组:
List(Array(self.viewModel.todos.enumerated()), id: \.element.id) { index, todo in ... }
这可以编译,但我们刚刚将性能问题转移到了视图中:每次评估这个body时,都有可能分配一个全新的数组。
但即使可以将枚举集合直接传递给这些视图,通过索引来识别可变状态的元素也会引入一些其他问题。
虽然我们确实可以大大简化和提高通过索引下标修改元素的任何视图模型方法的性能:
class TodosViewModel: ObservableObject { ... func todoCheckboxToggled(at index: Int) { self.todos[index].isComplete.toggle() // TODO: 使用API客户端在后端更新待办事项 } }
但是我们添加到这个端点的任何异步工作都必须非常小心,不要在之后使用这个索引。索引不是一个稳定的标识符:待办事项可以随时移动和删除,一个瞬间标识"买生菜"的索引可能下一刻就标识"打电话给妈妈",更糟糕的是,可能是一个完全无效的索引,导致应用程序崩溃!
class TodosViewModel: ObservableObject { ... func todoCheckboxToggled(at index: Int) async { self.todos[index].isComplete.toggle() do { // ❌ 可能会更新错误的待办事项,或导致崩溃! self.todos[index] = try await self.apiClient.updateTodo(self.todos[index]) } catch { // 处理错误 } } }
每当你需要在执行某些异步工作后访问特定的待办事项时,你_必须_遍历数组:
class TodosViewModel: ObservableObject { ... func todoCheckboxToggled(at index: Int) async { self.todos[index].isComplete.toggle() // 1️⃣ 在开始异步工作之前获取待办事项的id引用 let id = self.todos[index].id do { // 2️⃣ 在后端更新待办事项 let updatedTodo = try await self.apiClient.updateTodo(self.todos[index]) // 3️⃣ 在异步工作完成后找到待办事项的更新索引 let updatedIndex = self.todos.firstIndex(where: { $0.id == id })! // 4️⃣ 更新正确的待办事项 self.todos[updatedIndex] = updatedTodo } catch { // 处理错误 } } }
标识集合旨在通过提供以人体工程学和高性能方式处理可识别元素集合的数据结构来解决所有这些问题。
大多数情况下,你可以简单地将Array
替换为IdentifiedArray
:
import IdentifiedCollections class TodosViewModel: ObservableObject { @Published var todos: IdentifiedArrayOf<Todo> = [] ... }
然后你可以通过基于id的下标直接修改元素,无需遍历,即使在执行异步工作后也是如此:
class TodosViewModel: ObservableObject { ... func todoCheckboxToggled(at id: Todo.ID) async { self.todos[id: id]?.isComplete.toggle() do { // 1️⃣ 在后端更新待办事项并在todos标识数组中修改它。 self.todos[id: id] = try await self.apiClient.updateTodo(self.todos[id: id]!) } catch { // 处理错误 } // 没有步骤 2️⃣ 😆 } }
你还可以简单地将标识数组传递给List
和ForEach
等视图,而不会出现任何复杂性:
List(self.viewModel.todos) { todo in ... }
标识数组设计用于与SwiftUI应用程序以及使用Composable Architecture编写的应用程序集成。
IdentifiedArray
是Apple的Swift Collections中OrderedDictionary
类型的轻量级包装器。它具有许多相同的性能特征和设计考虑,但更适合解决在应用程 序状态中保存_可识别_元素集合的问题。
IdentifiedArray
不会暴露任何可能导致破坏不变性的OrderedDictionary
细节。例如,OrderedDictionary<ID, Identifiable>
可以自由地保存其标识符与其键不匹配的值,或多个值可能具有相同的id,而IdentifiedArray
不允许这些情况发生。
与OrderedSet
不同,IdentifiedArray
不要求其Element
类型符合Hashable
协议,这可能难以或不可能实现,并引入了关于哈希质量等问题。
IdentifiedArray
甚至不要求其Element
符合Identifiable
。就像SwiftUI的List
和ForEach
视图接受一个id
键路径来获取元素的标识符一样,IdentifiedArray
可以使用键路径构造:
var numbers = IdentifiedArray(id: \Int.self)
IdentifiedArray
设计用于匹配OrderedDictionary
的性能特征。它已经使用Swift Collections Benchmark进行了基准测试:
如果你想讨论这个库或有关如何使用它解决特定问题的问题,有几个地方可以与其他Point-Free爱好者讨论:
Identified Collections的最新API文档可在这里获得。
这些概念(以及更多)在Point-Free中得到了深入探讨,这是一个由Brandon Williams和Stephen Celis主持的探索函数式编程和Swift的视频系列。
在Composable Architecture中使用IdentifiedArray
的内容在以下Point-Free集中进行了探讨:
所有模块都在MIT许可证下发布。有关详细信息,请参阅LICENSE。
AI小说写作助手,一站式润色、改写、扩写
蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。
字节跳动发布的AI编程神器IDE
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
AI助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。
选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。
专业的AI公文写作平台,公文写作神器
AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。
最新AI工具、AI资讯
独家AI资源、AI项目落地
微信扫一扫关注公众号