在 SwiftUI 中正确使用 Task { }

2024-04-19

我想了解正确的用法Task { }在以下 SwiftUI 代码中。我的目标是获得基本的了解以避免内存泄漏。

这是 SwiftUI 部分的示例代码:

struct MyView: View {
    @ObservedObject var viewModel: ViewModel

    var body: some View {
        VStack {
            Text(viewModel.publishedString)
        }
        .onAppear(perform: {
            Task {
                viewModel.resetUI()
                await viewModel.doSomeAsyncStuff()
            }
        })
        .onDisappear {
            Task {
                await viewModel.doAnotherAsyncStuff()
                viewModel.resetUI()
            }
        }
    }
}

The .onAppear { … } and .onDisappear { … }修饰符将调用 ViewModel 类的同步和异步函数。这Text(viewModel.publishedString)代表一个已发布的属性(使用@Published) 修改为viewModel.doSomeAsyncStuff() and viewModel.doAnotherAsyncStuff().

请记住,我需要向后兼容 SwiftUI 2.0,这就是为什么我不使用.task { }修饰符。

您能否确认我对本例中内存泄漏和保留周期的理解是否正确:

  1. 通话期间Task { … },将在 Task 闭包内创建 MyView 类型值的副本
  2. 该结构类型值的副本保存对ViewModel class
  3. 保留参考ViewModel不分配新内存(因为它只是一个指针,而结构的副本将分配任务关闭完成后释放的新内存
  4. 对 ViewModel 类的函数调用以及已发布的更新publishedStringTask 闭包中的属性将更新 SwiftUI 视图,因为 View 结构的所有副本都持有对 ViewModel 类的相同引用
  5. 完成任务关闭将取消分配视图结构的副本
  6. 如果初始 MyView 值(不是 Task 闭包内的副本)由于不再需要而必须从内存中取消分配,但 Task 闭包尚未完成,则仅在 ViewModel 引用之前保留强引用完成任务关闭。一旦任务关闭(在.onAppear { … } and .onDisappear { … })完成后,所有为 View 结构和 ViewModel 类引用分配的内存都将被释放。

@StateObject旨在消除使用的需要onAppear。该对象在视图第一次出现之前初始化,并在视图消失时取消初始化。所以你可以在对象的内部开始你的任务init并取消它deinit。注意,我们通常称这个对象为“Loader”而不是“View Model”,因为在 SwiftUI 中View结构加号@State已经是视图模型。

如果您想在任务每次出现时运行而不是第一次出现,那么您可以添加重新启动func取消并重新启动任务,然后从onAppear.

更新:我更多地考虑了这一点,我相信可以存储Task处理在一个@State从而重新实现类似的东西.task:

struct TaskTestView: View {
    @State var task: Task<Void, Never>?

     var body: some View {
        Text("Test")
        .onAppear {
            task = Task {
                try? await Task.sleep(for: .seconds(3))
                if Task.isCancelled {
                    print("cancelled")
                    return
                }
                print("complete")
            }
        }
        .onDissapear {
            task?.cancel()
        }
    }
} 

用这个测试:

struct TaskTestView2: View {
    @State var showing = false

    var body: some View {
        VStack {
            if (showing) {
                TaskTestView()
            }
            else {
                Text("Not showing")
            }
        }
        Button("Show/Hide") {
            showing.toggle()
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 SwiftUI 中正确使用 Task { } 的相关文章

  • 如何避免强制解包变量?

    我如何避免使用 执行强制解包操作 因为使用它通常是一个糟糕的选择 对于像下面这样的代码 什么是更好的选择 使用它使代码看起来更简单 并且因为 if 检查变量 被调用的永远不会为零 因此不会崩溃 我的老师向我们介绍了 bang 运算符 然后告
  • 如何将多个请求传输到 Firebase 以同时从多个节点获取数据

    我需要从 Firebase 数据库中的 4 个节点检索数据 根据设计 在 firebase 中 这只能通过触发 4 个查询来完成 就我而言 这 4 个查询是独立的 因为我已经知道每个查询的路径 我可以同时触发它们 我从 Frank van
  • 在 SwiftUI TextEditor 中设置光标位置

    有没有办法以编程方式将光标移动到特定文本行或在 SwifUI 中选择它TextEditor 例如 如果有一个TextEditor里面写着10行 当用户按下按钮时 光标将导航到第三行 或者文本将被选择 目前使用默认的 SwiftUI 是不可能
  • iOS UITest:如何找到UITableViewCell的AccessoryView?

    你好我正在学习UITests now 我有个问题 如何检测accessoryView的点击tableViewCell 在UI测试中 下面是我的tableViewCell 我想要检测细节闭合配件视图水龙头 像这样 app tables cel
  • 我可以在 where 子句中使用 or ( || ) 吗?

    我正在尝试延长Array类型 但我只希望类型为时可用的函数Int or Float 我知道我可以针对一种类型执行此操作 extension Sequence where Iterator Element Int 但我可以对多种类型执行此操作
  • SWIFT:+[CATransaction Synchronize] 在解码 HTML 实体时在事务中调用

    我正在制作一个获取博客 JSON 内容的应用程序 博客文章的标题显示在 tableView 中 获取的标题是 HTML 编码的 所以我用这段代码解码了它们 func configureCell cell UITableViewCell at
  • 为什么在快速合并两个视频或更改背景音乐后视频变成黑屏?

    在我的 ios 应用程序中 我想合并两个视频并更改背景音乐 我尝试过 对于普通视频来说效果很好 但是 当我选择任何延时视频 然后尝试合并或更改背景音乐时 视频变成全黑屏 对于我的应用程序 我使用 swift 4 2 和 xcode 10 我
  • Xcode 6 代码编辑器异常行为

    截至最近 我在使用 Xcode 6 代码编辑器时遇到了一些麻烦 最终导致编辑窗口中的焦点快速变化 在编辑文本时跳转到同一文件中完全不同的位置 一切就是这样开始的 最近 编辑器拒绝上下滚动 挂起 停止显示行号或任何其他文本 我该怎么做才能让它
  • 用于 Flutter 原生广告的 Objective-C 的 Swift 等效项

    我想为我的 Flutter 项目实现原生广告 它使用 Swift 而不是 Objective C https developers google com admob flutter native https developers googl
  • Swift 从照片库中获取视频的 NSData

    我使用 UIImagePickerController 从我的库中选择视频 我需要提取视频文件的 NSData 我使用以下操作从我的库中选择视频 但我的数据似乎为零 但是我的 AVPlayer 播放生成的 NSURL 中的视频 所以我知道问
  • NSAttributedString 和表情符号:位置和长度问题

    我正在使用 NSAttributedString 对来自 API 的文本的某些部分 如 Twitter 上的 mention 进行着色 API 为我提供了文本和代表文本中应着色的部分 或链接 标签等 的实体数组 但有时 颜色会因为表情符号而
  • 将本机 swift Set 转换为数组[重复]

    这个问题在这里已经有答案了 我需要将 Set 转换为 AnyObject 或 String 的数组 这可能吗 我知道使用 NSSet 我可以使用 allObjects 但对于本机集似乎没有任何函数 只需直接强制转换为数组即可 let arr
  • 在 Swift 中使用 Obj-C 完成块

    在 Objective C 中 我有一个完成块类定义为 File h typedef void MYCompletionBlock BOOL success NSDictionary result NSError error 然后 在 Sw
  • 数组扩展以按值删除对象

    extension Array func removeObject
  • 如何在 macOS 上的 SwiftUI 中设置拖动图像

    我正在尝试更改 GridView 的默认拖放预览图像 该图像似乎包含网格中的所有可见项目 据我了解 我应该能够设置NSItemProvider previewImageHandler块来自定义所使用的图像 我似乎找不到任何关于返回自定义图像
  • 如何执行条件segue

    我通过 IB 创建了一个 segue 单击按钮时 将转换到视图 A 在按钮单击操作中 我有performSegue withIdentifier sender 包裹在一个条件中 我希望仅当条件为真时才发生 segue 但是 一旦用户单击按钮
  • iOS-Swift UIApplication.shared.isIdleTimerDisabled = true 在 AppStore 审核后不起作用

    努力实现停止屏幕在某些情况下进入睡眠状态View Controller 我做了什么我已在运行 iOS 12 1 12 的物理 iPhone 6 上使用以下代码测试了我的应用程序 我设置了手机Dislpay Brigthness gt Aut
  • 使用本地化故事板进行即时本地化

    我正在开发一个应用程序 它有一个切换按钮可以在英语和阿拉伯语之间切换 并且应该是动态的 我正在使用该方法https github com maximbilan ios language manager https github com ma
  • FocusState Textfield 在工具栏 ToolbarItem 中不起作用

    让我解释一下 我有一个带有 SearchBarView 的父视图 我正在传递这样的焦点状态绑定 SearchBarView searchText object searchQuery searching object searching f
  • ios - ARKit - 如何创建旋转对象手势功能?

    我是 ARKit 新手 我想创建一个旋转对象的函数 这是我关于拖动和旋转对象的代码 Rotate object objc func rotateRecognized sender UIPanGestureRecognizer let sce

随机推荐

  • 需要用jquery将h3和div包装在包装器div中

    我有以下 HTML div class accordion h3 My title h3 div My content div h3 My title h3 div My content div h3 My title h3 div My
  • 如何从 Ionic 选项卡打开 Ionic 模态

    我有一个用例 我想通过单击 Ion 选项卡来打开 Ionic Modal 我们的应用程序有 4 个固定的ion tabs 其中一个选项卡当前转到评论表单 但它更适合作为模式 因此用户可以快速完成表单并返回到他们正在做的事情 模态框通常附加到
  • Python CSV 编写器截断长数字

    我目前正在开发一个项目 该项目需要生成一个包含大量信息的 CSV 文件作为最终输出 目前 我将所有数据存储在一个非常大的列表中 然后使用 CSV 包将其写入 CSV 文件 我的问题是其中一个数据字段包含一个非常长的数字 存储为字符串 但第
  • Swift 栈和堆的理解

    我想快速了解堆栈和堆中存储的内容 我有一个粗略的估计 您打印的所有内容和内存地址都不是值 它们存储在堆栈中 而作为值打印出来的内容则在堆上 基本上根据值和引用类型 我完全错了吗 或者 您可以提供堆栈 堆的可视化表示吗 As Juul htt
  • 如何在 Firebase 实时数据库中保存本地数据?

    我对 Kotlin 和编程非常陌生 目前正在制作包含事件的日历 当我想将这些事件连接到 firebase 时 我的问题就出现了 我正在使用在 git 中找到的一个示例 https github com kizitonwose Calenda
  • 使用鼠标滚动 DataGridView

    因此 我们都熟悉单击并按住鼠标按钮 然后将鼠标移动到网格边缘 列 行滚动并且选择范围增加的功能 我有一个基于 DataGridView 的控件 由于性能问题 我必须关闭 MultiSelect 并自行处理选择过程 现在单击 按住滚动功能也被
  • 在matlab中对矩阵元素求和的有效(最快)方法

    让我们有矩阵A say A magic 100 我见过两种计算矩阵所有元素之和的方法A sumOfA sum sum A Or sumOfA sum A 其中一个比其他更快 或更好的练习 吗 如果有的话是哪一个 或者它们都同样快 看来你无法
  • 使用 PHPMailer 附加文​​件

    我有一个 HTML 表单 可以选择上传文件 然后 我想将该文件作为附件与其余表单数据一起发送到电子邮件地址 我正在使用 PHP Mailer 我获取要发送的表单数据 例如姓名 电话号码等 我无法将图像与它一起发送 我已经提供了迄今为止的代码
  • 如何在 Android 应用程序中播放和停止 mp3 文件

    我在 eclipse 中创建了一个应用程序来播放和停止 mp3 文件 一切都很好 除了当我播放音频文件并停止它并且我想重播它时 播放 btn 不起作用 我想知道是否有人可以帮助我 提前致谢 代码如下 package ir polyglotc
  • 更改 NUnit 测试的名称

    我希望我的单元测试基于NUnit在 Visual Studio 测试资源管理器中命名的框架更易于理解 例如 而不是有Test Case 1 or TestCase1我最好有类似的东西Test Case 1 Category First Ca
  • Android Room:应用与嵌入对象相关的多列

    在我的 Android 应用程序中 我使用 Room 进行数据存储 我目前面临的问题是 我需要在嵌入对象的 Relation 中放入 2 列 因为关系依赖于 2 列 结构见下图 Entity tableName damages public
  • 从通用平面获取轴对齐坐标

    标题可能是错误的 因为我不知道足够的数学知识来实际用一个小句子描述我的问题 我有一个 3D 矢量闭环 我将其称为 3D 多边形 我需要对其执行仅 2D 操作 这将返回一个 不同的 2D 点集 我需要将这些新的 2D 点转换回 3D 我目前的
  • 如何将下拉菜单置于父选项卡下居中?

    我有以下 CSS HTML 设置http jsfiddle net UDAUY http jsfiddle net UDAUY 如何对齐下拉菜单字段使其在父选项卡下居中 如下所示 MENU 1 MENU 2 MENU 3 MENU 4 Fi
  • 如何让 ko.compated 处理对象内的可观察值

    我有一个相当简单的视图模型来保存数据数组并获取一个我想用来过滤数据的字符串 我有一些非常简单的标记来渲染它 如下所示 section class task list ul li li ul section
  • 具有备用序列的列

    我想创建一个 user widgets 表 该表由 user id 和 user widget id 主键 其中 user widget id 的工作方式类似于序列号 除了每个用户从 1 个开始 对此有通用或实用的解决方案吗 我正在使用 P
  • networkx 通过属性搜索节点

    我寻找更优雅的方法来从以下属性之一搜索有向图中的节点 g nx DiGraph g add nodes from 1 dict d 0 a 7 2 dict d 0 a 6 g add nodes from 11 dict d 1 a 4
  • Android Studio - 非法字符 8204 错误

    由于某种原因 在重建我的项目后 我收到非法字符错误 但我的代码中没有任何内容以红色下划线显示 有人可以告诉我出了什么问题以及如何解决吗 Error illegal character 8204 WCBankActivity java imp
  • Linux 内核模块 Makefile 不能包含相对路径

    我正在尝试构建 Linux 内核模块 KBUILD EXTRA SYMBOLS Module symvers KBUILD EXTRA SYMBOLS dir0 Module symvers KDIR kernel linux 4 9 IN
  • Silverlight 中的计时器

    除了System Threading Timer对象之外 还有其他可以在Silverlight中使用的Timer对象吗 查看 DispatcherTimer http msdn microsoft com en us library sys
  • 在 SwiftUI 中正确使用 Task { }

    我想了解正确的用法Task 在以下 SwiftUI 代码中 我的目标是获得基本的了解以避免内存泄漏 这是 SwiftUI 部分的示例代码 struct MyView View ObservedObject var viewModel Vie