首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

使用SwiftUI / Combine,如何避免在ViewModel中放置可取消标签

在使用SwiftUI / Combine开发过程中,避免在ViewModel中放置可取消标签的方法如下:

  1. 使用Combine提供的AnyCancellable类型来管理订阅和取消订阅。AnyCancellable是一个可以持有和取消订阅的对象,可以通过将其存储在ViewModel中来管理订阅。
  2. 在ViewModel中创建一个私有的Set<AnyCancellable>属性,用于存储所有的订阅。这个属性可以在ViewModel的生命周期内持有所有的订阅。
  3. 在ViewModel中,使用sink方法来订阅Combine流,并将返回的AnyCancellable对象添加到上一步创建的Set<AnyCancellable>属性中。
  4. 当ViewModel不再需要订阅时,例如在视图销毁时,可以在适当的生命周期方法中调用cancel()方法来取消所有的订阅。例如,在SwiftUI的onDisappear方法中调用cancel()方法。

下面是一个示例代码:

代码语言:txt
复制
import SwiftUI
import Combine

class ViewModel: ObservableObject {
    private var cancellables = Set<AnyCancellable>()
    
    func fetchData() {
        // 使用Combine进行网络请求
        URLSession.shared.dataTaskPublisher(for: URL(string: "https://example.com")!)
            .map { $0.data }
            .decode(type: MyData.self, decoder: JSONDecoder())
            .sink { completion in
                // 处理请求完成的情况
            } receiveValue: { data in
                // 处理请求成功的情况
            }
            .store(in: &cancellables) // 将订阅添加到Set中
    }
    
    func cancelSubscriptions() {
        cancellables.forEach { $0.cancel() } // 取消所有订阅
    }
}

struct ContentView: View {
    @StateObject private var viewModel = ViewModel()
    
    var body: some View {
        Text("Hello, World!")
            .onAppear {
                viewModel.fetchData()
            }
            .onDisappear {
                viewModel.cancelSubscriptions()
            }
    }
}

在上面的示例中,ViewModel使用cancellables属性来存储所有的订阅。在fetchData()方法中,订阅了一个网络请求的Combine流,并将返回的AnyCancellable对象添加到cancellables中。在视图销毁时,调用cancelSubscriptions()方法来取消所有的订阅。

这样,我们就可以在ViewModel中避免放置可取消标签,并且能够正确地管理订阅和取消订阅。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Swift 掌握 Observation 框架

新的观察框架与 Swift 并发功能结合使用,允许我们替代 Apple 公司看起来已经过时的 Combine 框架。下面将介绍如何使用观察框架来处理应用程序的数据流。...之后,我们可以观察 Store 类型的任何变量。我们 Store 类型只有一个变量,用于定义存储的状态。另一个字段是一个永不更改的 let 常量。...SwiftUI 自动跟踪 SwiftUI ,你不需要使用 withObservationTracking 函数来观察更改。SwiftUI 自动跟踪视图正文中使用的任何可观察类型属性的更改。...我们不需要 @ObservedObject 属性包装器来跟踪可观察类型的更改,但我们仍然需要 @StateObject 替代项以 SwiftUI 生命周期中存活。...新的观察框架结合了 Swift 并发功能,使我们能够替代苹果看似已经过时的 Combine 框架。总的来说,新的观察框架使 SwiftUI 的数据流管理更加轻松和高效。

23021
  • 构建稳定的预览视图 —— SwiftUI 预览的工作原理

    可惜的是,Toomas Vahter文章没有告诉读者崩溃原因。我借用这段代码来与大家一起探究预览功能是如何工作的。...了解了问题所在,我们还可以使用其他两种方式来解决之前的代码无法预览中使用的问题。 方法一 将 Item 从 ContentView 移出来,放置到与 ContentView 同级的代码位置。...接下来,让我们继续查看 Xcode 是如何加载预览视图的。。 项目的 Derived Data 目录查找尾缀为 .preview-thunk.dylib 的文件。...开发者使用预览时需要清醒地认识到其局限性,并避免预览实现超出其能力范围的功能。 接下来 本文中,我们探讨了 Xcode 预览功能的实现原理,并指出其存在一定局限性。...在下一篇文章,我们将从开发者的角度审视预览功能:它的设计目的、最适宜的使用场景以及如何构建稳定高效的预览。

    53610

    架构之路 (五) —— VIPER架构模式(一)

    开始 首先看下主要内容: 本教程,您将了解如何SwiftUICombine使用VIPER体系结构模式,同时构建一个允许用户创建公路旅行的iOS应用程序,来自翻译。...VIPER为这种情况提供了一种替代方案,可以与SwiftUICombine结合使用,帮助构建具有清晰架构的应用程序,该架构有效地分离了所需的不同功能和职责,如用户界面、业务逻辑、数据存储和网络。...在此过程,您还将了解您的iOS项目中的SwiftUICombine。 打开启动项目。这包括一些代码,让你开始: 当你构建其他视图时,ContentView会启动它们。...然后,TripDetailPresenter,将其内容设置为: import SwiftUI import Combine class TripDetailPresenter: ObservableObject...当您将其放置NavigationView时,该链接将成为一个按钮,将destination推送到导航堆栈上。 content块可以是任何一个SwiftUI视图。

    17.4K10

    干货 | 深入浅出Apple响应式框架Combine

    事实上SwiftUI的数据驱动就是依赖Combine。 本文将深入浅出地介绍Combine的基本概念和原理,然后通过具体demo详细阐述其实际编码的应用。...Combine的各种operators是定义Publisher的各种Extension各自的扩展实现了内置的classes或者structures。...我们通过URLSession内置的dataPublisher发送网络请求解析来说明用法,目的是为了说明Combine的异步API以及异步API如何使用Operator。代码示例如下图: ?...3.2.2 Bind ViewModel 下面是VC具体bind ViewModel的示例: ?...1)我们实现了bindView()方法,该方法将UI控件通过3.1封装的自定义UIControlPublisher实现UI控件的事件绑定,并且将Publisher产生的值绑定到ViewModel对应的

    3.8K31

    Text 实现基于关键字的搜索和定位

    欢迎大家 Discord 频道[2] 中进行更多地交流前些日子,一位网友聊天室中就如下的 问题[3] 与大家进行了交流与探讨 —— 如何通过 Text + AttributedString 实现类似文章关键字检索的功能...请阅读 优化 SwiftUI List 显示大数据集的响应效率[6] 以及 避免 SwiftUI 视图的重复计算[7] 两篇文章,了解更多有关性能优化方面的内容通过 currentPostion 获取需要滚动到的...修饰器的时候,我们通常会用两种方式添加搜索栏 —— 1、通过 VStack 将搜索栏放置 List 下方,2、使用 overlay 将搜索栏放置 List 视图的上层。...我们需要采用如下方式避免因此而导致的应用卡顿:确保搜索操作运行于后台线程过滤关键字响应,避免因为输入太快导致的无效搜索操作我们通常会在 Combine 采用 .subscribe(on: ) 来设定之后的...范例代码,我使用了 聊聊 Combine 和 async/await 之间的合作[13] 一文中介绍的方法,通过自定义 Publisher ,将 async/await 方法嵌入到 Combine

    4.2K30

    Ask Apple 2022 与 SwiftUI 有关的问答(上)

    使用 environmentObject 的情况下,如何避免创建实例的视图被重新计算Q:如何避免重新计算顶层视图 body 的情况下,不同子树的两个子视图之间共享状态( 例如 ObservableObject...这在 SwiftUI 仍适用,还是说 struct 本身现在被视为 viewModel ?A:SwiftUI 试图与应用程序的整体架构无关。...常规宽度下,我们详细视图中有一个带有导航堆栈的侧边栏。紧凑宽度下,我们有一个标签栏,每个标签都有一个导航堆栈。...例如,在你的模型,有多个路径,每个标签都有一个,但在 split view ,只投射其中一个路径的细节。...image-20221022135326560San Francisco 宽度风格Q:如何SwiftUI 如何使用 SF 字体家族新增的三种宽度风格( Compressed、Condensed、Expanded

    12.2K20

    如何在Xcode下预览含有Core Data元素的SwiftUI视图

    结合两年来我SwiftUI使用Core Data的经验和教训,我们将在本文中探讨: •导致SwiftUI预览崩溃的部分原因•如何在之后的开发避免类似的崩溃出现•如何在Xcode安全可靠地预览含有...Redux-like SwiftUI + Combine是苹果推出的声明+响应式结构方案。SwiftUI应用程序的开发逻辑非常类似于Redux设计模式。...SwiftUI通常采用Redux的开发模式,通过将获取到的Core Data数据转换成标准的Swift结构从而避免视图中使用托管对象上下文或托管对象。...,同时由于转换后的ViewModel的属性类型可控(无需类型转换、无需判定可选值等),便于代码中使用。...SwiftUI+Core Data使用,痛苦和快乐始终相伴而行。

    5.1K10

    如何SwiftUI 的列表变得更加灵活

    SwiftUI 初版的概念和 API 编写的,下面让我们尝试使用新功能来为我们的列表实现自定义样式,并且使代码更加健壮。...使用新速记语法 让我们从一个很小的特性开始,这是一个非常受欢迎的变化,可以使用类似 enum 的速记语法来引用 SwiftUI 附带的任何内置 ListStyle 类型。...元素绑定和自定义滑动操作 接下来,让我们看看如何将完全自定义的滑动操作添加到列表。...为了演示这种情况,我们 List 嵌套一个 ForEach (因为 SwiftUI,列表变化一版都是由 ForEach 触发的,而不是由 List 触发的)。...} } } 要了解有关 async/await 的更多信息以及如何SwiftUI使用,请查看昨天的这篇文章[1],不要错过真正重要的“ Swift 认识 async/await[2]

    4.9K41

    【译】LiveData with Coroutines and Flow

    如果我们ViewModel中有一个对Activity的引用,我们将需要确保。 当视图被销毁时清除它 如果视图处于transitional状态,避免访问。...你一个Activity的onStart启动一个操作,你onStop停止它。 你ViewModel的initblock启动一个操作,然后onCleared()停止它。...ViewModel + LiveData 到目前为止,我们已经看到了如何启动一个coroutine,但没有看到如何从它那里接收一个结果。你可以像这样使用一个MutableLiveData。...的任何函数(如delay),你应该知道它们都是可取消的,这意味着它们会为你做这种检查。...在这种情况下,你可以使用suspendCoroutine或suspendCancellableCoroutine。 (我不知道你为什么要使用可取消的版本,但请在评论告诉我!)

    1.4K10

    用AsyncAwait重建SwiftU的Redux-like状态容器

    用Async/Await重建SwiftU的Redux-like状态容器 本文介绍了如何使用Swift 5.5版本的Async/Await功能重构SwiftUI的状态容器代码。...2.0版本 通过阅读、学习Majid的文章Redux-like state container in SwiftUI[4],健康笔记[5]2.0,我重构了Store的代码。...并且使用Combine提供的线程调度,保证了只主线程上修改State。...两个版本都严重依赖Combine,都是采用Combine来进行异步代码的生命周期管理,并且2.0又是通过Combine提供的.receive(on: DispatchQueue.main)来进行的线程调度...•使用@MainActore保证State只能在主线程被修改•dispatch创建即发即弃的Task完成副作用生命周期管理•同2.0版本类似,副作用方法返回Task

    1.8K20

    如何在 Swift 取消一个后台任务

    本文演示了如何明确地取消一个任务,并展示了子任务是如何自动取消的。 该代码建立在在 Swift 中使用 async let 并行的运行后台任务编写的AsyncLetApp之上。...一个取消按钮被添加到视图中,其点击事件是ViewModel调用取消方法。...ViewModel添加了一些日志记录,以便在文件下载增加时和文件isDownloading属性被设置为false时打印出来。...的子任务 SwiftUI 取消和恢复后台任务 结论 异步编程,重要的是停止任何不需要的后台任务以节省资源并避免后台任务干扰应用程序的任何不良副作用。...异步编程,必须停止任何不需要的后台任务,以节省资源,并避免后台任务干扰App带来的任何不必要的副作用。

    2.8K30

    深度解读 Observation —— SwiftUI 性能提升的新途径

    此外, SwiftUI ,引用类型的数据源(Source of Truth)采用了基于 Combine 框架的 ObservableObject 协议实现。...如何声明可观察对象 使用 Combine 框架,我们可以这样声明一个可被观察的引用类型: class Store: ObservableObject { @Published var firstName...如何在视图中使用可观察对象 视图中声明可观察对象 与遵守 ObservableObject 协议的 Source of Truth 不同,我们会在视图中使用 @State 来确保可观察对象的声明周期。...SwiftUI 的视图如何观察属性的变化 根据 Observation 框架的工作原理,我们可以推测 SwiftUI 大概会采用下面的方法可观察属性与视图更新之间创建联系: struct A:View...更多对视图优化技巧,请阅读 避免 SwiftUI 视图的重复计算[5] 一文。

    55620

    理解协程、LiveData 和 Flow

    实际应用,以我们的 Android Dev Summit 应用为例,里面涉及到的作用域非常多。...此外我们还有很多 Activity,而和它们相关的 ViewModel 的作用域就是这些 Activity。 您也可以自定义作用域。比如针对导航组件,您可以将作用域限制登录流程或者结账流程。...如何启动和取消协程 Jetpack 组件里,我们为各个组件提供了对应的 scope,比如 ViewModel 就有与之对应的 viewModelScope,如果您想在这个作用域里启动协程,使用如下代码即可...但我们有必要讲一讲如何在协程内部来手动取消协程。 这里补充一个大前提: 所有 kotlin.coroutines 的 suspend 方法都是可取消的。...如果我们想监听多个值的话,该如何操作呢? 第一种选择是 ViewModel 之外也使用 LiveData: ?

    2.2K20

    SwiftUI:“看我展示52张扑克牌,很快啊!”

    思路 使用 SwiftUI 创建 UI 结构; 使用 swift 的枚举和结构体实现数据生成,通过 viewModel 整合数据用于展示(交互暂时未做,因此不涉及 MVVM 设计模式的数据绑定)。...感受 swift 语法构建数据类型时比 OC 方便太多了,枚举和结构体(值类型,copy-on-write)都很强大。...非共享数据优先使用结构体,类一般只用于 viewModel,用于数据共享给多个 view。...SwiftUI 使用声明式方法构建 UI,代码方面简洁了很多,一套代码,三端适用(iOS,iPadOS,macOS(M1))。而且支持实时预览,大大提高了 UI 开发效率!...距离 APP 支持最低版本 iOS13 应该也不远了(微信目前最低支持 iOS11.0),iOSer 们,是时候学习一波 SwiftUI 了!随便再温习下 swift 相关语法。

    98650

    SwiftUI使用 NSUbiquitousKeyValueStore 同步数据

    本文将对其用法做以简单介绍,着重探讨如何便捷地 SwiftUI使用 NSUbiquitousKeyValueStore。...对于不返回可选值的类型,应避免使用简便方法来获取值。... SwiftUI 视图中使用 NSUbiquitousKeyValueStore 本节,我们将在不使用任何第三方库的情况下,实现 SwiftUI 视图对 NSUbiquitousKeyValueStore...使用第三方库的情况下, SwiftUI 视图中可以通过桥接@State 数据的形式,将 NSUbiquitousKeyValueStore 的变化同视图联系起来。...因此需要寻找一种适合 SwiftUI 的方式,将键值对统一配置、集中管理。 @AppStorage 研究[7] 一文,我介绍过如何对@AppStorage 进行统一管理、集中注入的方法。

    4.9K40
    领券