swift-verge

swift-verge

Swift平台高效状态管理库Verge

Verge是一个为Swift平台设计的高性能状态管理库。它支持SwiftUI和UIKit,提供轻量级且易用的方法管理应用状态。Verge具备并发处理能力,提供异步操作和大量实体管理API,能有效解决大型复杂应用中的状态更新问题。该库无需复杂的操作和reducer,简化了状态管理流程。

Verge状态管理iOS开发Swift多线程Github开源项目
<p align="center"> <a href="https://vergegroup.org"> <img width="128" alt="VergeIcon" src="https://yellow-cdn.veclightyear.com/835a84d5/889a2815-7044-4ffe-b9d0-eda72b64dfd8.png"> </a> </p> <h1 align="center">Verge.swift</h1> <p align="center"> <b>📍一个适用于iOS的高效状态管理架构 - UIKit, SwiftUI📍</b><br/> <sub>_ 获得单向数据流的更简单方式 _</sub><br/> <sub>_ 支持并发处理 _</sub><br/> </p>

支持这个项目

<a href="https://www.buymeacoffee.com/muukii"> <img width="160" alt="yellow-button" src="https://yellow-cdn.veclightyear.com/835a84d5/0cac9daa-a890-4666-ba04-44a665b38b4a.png"> </a>

Verge:一个适用于SwiftUI和UIKit的高性能、可扩展的状态管理库

Verge是一个为Swift设计的高性能、可扩展的状态管理库,考虑到了真实世界的使用场景。它提供了一种轻量级且易于使用的方法来管理应用程序状态,无需复杂的操作和减速器。本指南将带您了解在Swift项目中使用Verge的基础知识。

核心概念和动机

Verge的设计考虑了以下概念:

  • 受Flux库的启发,但注重将存储模式作为核心概念。
  • 存储模式是Flux和Redux中的基本概念,专注于使用单一真实来源在组件之间共享状态。
  • Verge不规定如何管理修改状态的操作。相反,它提供了一个简单的commit函数,该函数接受描述如何更改状态的闭包。
  • 用户可以在Verge之上构建额外的层,例如实现基于枚举的操作以实现更结构化的状态管理。
  • Verge支持多线程,确保快速、安全和高效的操作。
  • 兼容UIKit和SwiftUI。
  • 包含用于处理实际应用程序开发用例的API,如管理异步操作。
  • 解决了在大型和复杂应用程序中更新状态的复杂性。
  • 提供了一个ORM,用于高效管理大量实体。
  • 为业务导向的应用程序设计。

开始使用

开始使用

要使用Verge,请按照以下步骤操作:

  1. 定义一个符合Equatable协议的状态结构体。
  2. 使用初始状态实例化一个Store
  3. 使用存储实例上的commit方法更新状态。
  4. 使用sinkState方法订阅状态更新。

定义您的状态

创建一个代表应用程序状态的状态结构体。您的状态结构体应符合Equatable协议。这允许Verge检测状态的变化并在必要时触发更新。

示例:

struct MyState: StateType { var count: Int = 0 }

实例化存储

使用应用程序的初始状态创建一个Store实例。Store类接受两个类型参数:

  • 第一个类型参数表示应用程序的状态。
  • 第二个类型参数表示您想与存储一起使用的任何中间件。如果不需要任何中间件,请使用Never

示例:

let store = Store<_, Never>(initialState: MyState())

更新状态

要更新应用程序状态,请使用Store实例上的commit方法。commit方法接受一个闭包,该闭包有一个参数,即对状态的可变引用。在闭包内部,根据需要修改状态。

示例:

store.commit { $0.count += 1 }

订阅状态更新

要在状态更改时接收更新,请使用Store实例上的sinkState方法。此方法接受一个闭包,该闭包接收更新后的状态作为其参数。每当状态发生变化时,都会调用该闭包。

示例:

store.sinkState { state in // 接收状态的更新 } .storeWhileSourceActive()

最后的storeWhileSourceActive()调用是Verge提供的一种方法,用于自动管理订阅的生命周期。它会在源(在本例中为store实例)处于活动状态时保留订阅。

就是这样!您现在了解了使用Verge在Swift应用程序中管理状态的基础知识。对于更高级的用例和其他功能,请参阅官方Verge文档和GitHub存储库。

使用存储的活动进行事件驱动编程

在某些情况下,事件驱动编程对于创建响应迅速和高效的应用程序至关重要。Verge库的存储活动功能旨在满足这一需求,允许开发人员在其项目中无缝处理事件。

当您的应用程序需要事件驱动编程时,存储的活动就派上用场了。它使您能够独立于主存储管理来管理事件和相关逻辑,促进了清晰和有组织的代码结构。这种关注点分离简化了整体开发过程,并使维护和扩展应用程序变得更加容易。

通过利用存储的活动功能,您可以在保持存储管理完整的同时高效地处理应用程序中的事件。这确保了您的应用程序保持高性能和可扩展性,使您能够使用Verge库构建强大可靠的Swift应用程序。

以下是使用存储的活动的示例:

let store: Store<MyState, MyActivity> store.send(MyActivity.somethingHappened)
store.sinkActivity { (activity: MyActivity) in // 处理活动 } .storeWhileSourceActive()

在SwiftUI中使用Verge

要在SwiftUI中使用Verge,您可以利用StoreReader在SwiftUI视图中订阅状态更新。以下是如何做到这一点的示例:

import SwiftUI import Verge struct ContentView: View { @StoreObject private var viewModel = CounterViewModel() var body: some View { VStack { StoreReader(viewModel.store) { state in Text("计数: \(state.count)") .font(.largeTitle) } Button(action: { viewModel.increment() }) { Text("增加") } } } } final class CounterViewModel: StoreComponentType { struct State: Equatable { var count: Int = 0 } let store: Store<State, Never> = .init(initialState: .init()) func increment() { commit { $0.count += 1 } } }

在这个例子中,StoreReader用于读取MyViewModel存储的状态。这允许您在SwiftUI视图中访问和显示状态。此外,您可以通过直接调用存储上的方法来执行操作,如示例中的按钮所示。

这个新部分将帮助用户理解如何在SwiftUI中使用Verge,使他们能够在SwiftUI视图中有效管理状态。如果您有任何进一步的建议或更改,请告诉我!

StoreObject属性包装器:

SwiftUI提供了@StateObject属性包装器来创建和管理遵循ObservableObject协议的给定对象的持久实例。然而,每当ObservableObject更新时,StateObject都会导致视图刷新。

在Verge中,我们引入了StoreObject属性包装器,它在视图的生命周期内实例化一个Store对象,但当Store更新时不会导致视图刷新。

当您想以更细粒度的方式管理Store,而不希望Store更改时导致整个视图刷新时,这很有用。相反,Store的更新可以通过StoreReader来处理。

在UIKit中使用Verge

以下是Verge在UIViewController中的简单使用示例:

class MyViewController: UIViewController { private struct State: Equatable { var count: Int = 0 } private let store: Store<State, Never> = .init(initialState: .init()) private let label: UILabel = .init() override func viewDidLoad() { super.viewDidLoad() setupUI() // 订阅store的状态更新 store.sinkState { [weak self] state in guard let self = self else { return } // 使用ifChanged检查值是否已更新 state.ifChanged(\.count) { count in self.label.text = "Count: \(count)" } } .storeWhileSourceActive() } private func setupUI() { // 为简洁起见省略 } private func incrementCount() { store.commit { $0.count += 1 } } }

使用sinkStateChanged<State>ifChanged在UIKit中高效更新状态

在事件驱动的UIKit中,高效更新组件至关重要,只在需要时更新它们。Verge库提供了一种使用sinkState方法、Changed<State>类型和ifChanged方法来实现这一点的方法。

当使用sinkState方法时,您提供的闭包会接收包装在Changed<State>类型中的最新状态。这个包装器还包含了先前的状态,允许您使用ifChanged方法确定哪些属性已更新。

以下是在UIKit中使用sinkStateifChanged高效更新组件的示例:

store.sinkState { $0.ifChanged(\.myProperty) { newValue in // 只有当myProperty发生变化时才更新组件 } }

在这个例子中,只有当myProperty发生变化时,组件才会更新,确保在基于UIKit的应用程序中高效更新。

相比之下,SwiftUI使用声明式视图结构,这意味着更新视图时较少需要检查状态变化。然而,在使用UIKit时,使用sinkStateChanged<State>ifChanged有助于保持应用程序的性能和响应性。

使用TaskManager进行异步操作

Verge的Store包含一个TaskManager,允许您调度和管理异步操作。这个功能简化了处理异步任务的过程,同时保持它们与您的Store相关联。

基本用法

要使用TaskManager,只需在Store实例上调用task方法,并提供包含异步操作的闭包:

store.task { await runMyOperation() }

使用键和模式进行任务管理

TaskManager还允许您基于键和模式管理任务。您可以为每个任务分配一个唯一的键,并指定其执行模式。这使您可以根据任务的键控制任务的执行行为。

例如,您可以使用.dropCurrent模式来丢弃任何当前正在运行的具有相同键的任务,并立即运行新任务:

store.task(key: .init("MyOperation"), mode: .dropCurrent) { // }

这个功能为您提供了对任务执行方式的细粒度控制,确保您的应用程序在处理多个异步操作时保持响应和高效。

高级用法:管理复杂应用程序的多个存储

理论上,在单个存储中管理整个应用程序状态是理想的。然而,在大型和复杂的应用程序中,计算复杂度可能变得很高,导致性能问题和应用程序响应缓慢。在这种情况下,建议将状态分离到多个存储中,并根据需要集成它们。

通过将状态分为多个存储,您可以减少与状态更新相关的复杂性和开销。每个存储可以管理应用程序状态的特定部分,确保更新高效快速地执行。这种方法还促进了代码的更好组织和关注点分离,使得随着时间的推移更容易维护和扩展您的应用程序。

要使用多个存储,为应用程序状态的不同部分创建单独的Store实例,然后根据需要连接它们。这可能涉及将存储实例传递给子组件或在兄弟组件之间共享存储。通过这种方式构建应用程序,您可以确保应用程序状态的每个部分都得到高效和有效的管理。

在存储之间复制状态

要在存储之间复制状态,您可以使用sinkState方法和ifChanged函数,仅在状态发生变化时触发更新。以下是一个示例:

store.sinkState { $0.ifChanged(\.myState) { value in otherStore.commit { $0.myState = value } } }

在这个例子中,当store中的myState状态发生变化时,新值会被提交到otherStore。这种方法允许您高效地同步多个存储之间的状态。

使用Derived进行高效计算属性

Verge的Derived功能允许您基于存储的状态创建计算属性,并高效地订阅更新。这个功能可以通过减少不必要的计算和更新来帮助您优化应用程序。Derived的灵感来自reselect库,并提供类似的功能。

创建派生属性

要创建派生属性,您将使用store.derived方法。这个方法接受一个描述如何生成派生数据的Pipeline对象:

let derived: Derived<Int> = store.derived(.select(\\.count))

您可以使用selectmap来生成派生数据。select用于直接从状态中获取值,而map可以用于基于状态生成新值,类似于map函数:

let derived: Derived<Int> = store.derived(.map { $0.count * 2 })

Pipeline会检查派生数据是否从先前的值更新。如果没有变化,Derived不会发布任何更改。

链接派生实例

您可以从现有的 Derived 实例创建另一个 Derived 实例,有效地将它们链接在一起:

let anotherDerived: Derived<String> = derived.derived(.map { $0.description })

订阅派生属性更新

要订阅派生属性的更新,您可以使用 sinkState 方法,就像对 store 一样:

derived.sinkState { value in // 处理派生属性的更新 } .storeWhileSourceActive()

通过使用 Derived 处理计算属性并订阅更新,您可以确保应用程序保持高效和性能,避免不必要的计算和状态更新。

VergeNormalization 简介

状态管理在构建高效和可维护的应用程序中起着至关重要的作用。状态管理的一个重要方面是以简化数据操作和使用的方式组织数据。这就是规范化变得至关重要的原因。

规范化是一种以消除冗余并确保数据一致性的方式构建数据的过程。它在状态管理库中至关重要,因为它显著降低了操作的计算复杂性,并使状态管理变得更加容易。

文档:

让我们通过一个例子来说明规范化和非规范化数据结构之间的区别。

非规范化数据结构:

posts: - id: 1 title: "文章 1" author: id: 1 name: "爱丽丝" - id: 2 title: "文章 2" author: id: 1 name: "爱丽丝" - id: 3 title: "文章 3" author: id: 2 name: "鲍勃"

在非规范化结构中,作者数据在每篇文章中都重复出现,这可能导致不一致性,并使状态管理变得更加困难。

规范化数据结构:

entities: authors: 1: id: 1 name: "爱丽丝" 2: id: 2 name: "鲍勃" posts: 1: id: 1 title: "文章 1" authorId: 1 2: id: 2 title: "文章 2" authorId: 1 3: id: 3 title: "文章 3" authorId: 2

在规范化结构中,作者数据与文章分开存储,消除了数据冗余并确保了数据一致性。文章和作者之间的关系通过文章中的 authorId 字段表示。

VergeORM 旨在有效处理状态管理库中的规范化。通过利用 VergeORM,您可以简化状态管理,降低操作的计算复杂性,并提高应用程序的整体性能和可维护性。

定义实体

以下是如何定义 BookAuthor 实体的示例:

struct Book: EntityType { typealias EntityIDRawType = String var entityID: EntityID { .init(rawID) } let rawID: String var name: String = "initial" let authorID: Author.EntityID } struct Author: EntityType { typealias EntityIDRawType = String var entityID: EntityID { .init(rawID) } let rawID: String var name: String = "" }

定义数据库模式

要在状态中存储实体,您需要定义数据库模式:

@NormalizedStorage struct Database { @Table var books: Tables.Hash<Book> = .init() @Table var authors: Tables.Hash<Book> = .init() }

在状态中嵌入数据库

Database 嵌入到应用程序的状态中:

struct RootState: StateType { var database: Database = .init() }

存储和查询实体

以下是使用 store 属性存储和查询实体的示例:

// 存储实体 store.commit { $0.database.performBatchUpdates { context in let authors = (0..<10).map { i in Author(rawID: "\(i)") } let result = context.modifying.author.insert(authors) } } // 查询实体 let book = store.state.database.db.book.find(by: .init("1")) let author = store.state.database.db.author.find(by: .init("1"))

在这个示例中,我们使用 store.commit 对数据库执行批量更新。我们向 author 实体表中插入一组新的作者。然后,我们使用 store.state.database.db 通过它们的标识符查询 bookauthor 实体。

通过使用 VergeNormalization,您可以使用规范化的数据结构高效地管理应用程序状态,这简化了状态管理,降低了操作的计算复杂性,并提高了应用程序的整体性能和可维护性。

安装

SwiftPM

Verge 支持 SwiftPM。

演示应用程序

本仓库在 Demo 目录中包含多个演示应用程序。 我们正在寻找您的演示应用程序以在此处列出! 请通过 Issue 告诉我们!

致谢

作者

🇯🇵 Muukii (Hiroshi Kimura)

许可证

Verge 基于 MIT 许可证发布。

编辑推荐精选

Trae

Trae

字节跳动发布的AI编程神器IDE

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
问小白

问小白

全能AI智能助手,随时解答生活与工作的多样问题

问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。

热门AI助手AI对话AI工具聊天机器人
Transly

Transly

实时语音翻译/同声传译工具

Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。

讯飞智文

讯飞智文

一键生成PPT和Word,让学习生活更轻松

讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。

AI办公办公工具AI工具讯飞智文AI在线生成PPTAI撰写助手多语种文档生成AI自动配图热门
讯飞星火

讯飞星火

深度推理能力全新升级,全面对标OpenAI o1

科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。

热门AI开发模型训练AI工具讯飞星火大模型智能问答内容创作多语种支持智慧生活
Spark-TTS

Spark-TTS

一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型

Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。

咔片PPT

咔片PPT

AI助力,做PPT更简单!

咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。

讯飞绘文

讯飞绘文

选题、配图、成文,一站式创作,让内容运营更高效

讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。

热门AI辅助写作AI工具讯飞绘文内容运营AI创作个性化文章多平台分发AI助手
材料星

材料星

专业的AI公文写作平台,公文写作神器

AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。

openai-agents-python

openai-agents-python

OpenAI Agents SDK,助力开发者便捷使用 OpenAI 相关功能。

openai-agents-python 是 OpenAI 推出的一款强大 Python SDK,它为开发者提供了与 OpenAI 模型交互的高效工具,支持工具调用、结果处理、追踪等功能,涵盖多种应用场景,如研究助手、财务研究等,能显著提升开发效率,让开发者更轻松地利用 OpenAI 的技术优势。

下拉加载更多