fatbobman / blogComments

1 stars 0 forks source link

避免 SwiftUI 视图的重复计算 | 肘子的Swift记事本 #157

Open fatbobman opened 2 years ago

fatbobman commented 2 years ago

https://www.fatbobman.com/posts/avoid_repeated_calculations_of_SwiftUI_views/

随着近年来有关 SwiftUI 的文章与书籍越来越多,开发者应该都已经清楚地掌握了 —— “视图是状态的函数” 这一 SwiftUI 的基本概念。每个视图都有与其对应的状态,当状态变化时,SwiftUI 都将重新计算与其对应视图的 body 值。如果视图响应了不该响应的状态,或者视图的状态中包含了不该包含的成员,都可能造成 SwiftUI 对该视图进行不必要的更新( 重复计算 ),当类似情况集中出现,将直接影响应用的交互响应,并产生卡顿的状况。通常我们会将这种多余的计算行为称之为过度计算或重复计算。本文将介绍如何减少( 甚至避免 )类似的情况发生,从而改善 SwiftUI 应用的整体表现。

skywalkerlw commented 2 years ago

你提到了“可以考虑使用第三方库,对状态进行切分,减少视图刷新几率”,请教一下,有哪些第三方库你觉得不错的?

fatbobman commented 2 years ago

你提到了“可以考虑使用第三方库,对状态进行切分,减少视图刷新几率”,请教一下,有哪些第三方库你觉得不错的?

很难说哪个是不错的,因为优势都是通过牺牲一些其他的灵活性而获取的。使用一个第三方框架来构造你的数据流必须从整体考量才能判断出是否值得。

TCA 是当下正火的项目,它提供了对 State 进行切分( scope ) 以及其他众多的功能。不过,它也是一个巨大的项目,你需要衡量是否有必要为项目引入如此巨大的一个库

SwiftTinyRedux 是一个规模小的多的库,也提供了类似的能力

Trellis 轻量级、事件驱动的架构框架

切分 State 是一个笼统的说法,可以从设计角度、代码角度、顶层-底层等多个方面来贯彻这种逻辑。总之,需要对 SwiftUI 、Combine 等有更加深入的了解,找寻到适合自己的方式。没有什么必然适用的现成方案。

okmyself commented 1 year ago

您提到了

任何可以在当前视图之外进行改动的 Source of Truth( 符合 DynamicProperty 协议的属性包装器 ),只要在视图类型中声明了,无论是否在视图 body 中被使用,在它给出刷新信号时,当前视图都将被刷新。

我在当前视图中定义了一个updateViewFlag@State布尔变量,该变量没有在body视图中被使用(除了onReceive中),在视图的body末尾,通过onReceive接收一个外部的publisher的消息,执行updateViewFlag.toggle(),在onReceive收到消息后发现body没有被重新计算,请问该如何理解呢?

fatbobman commented 1 year ago

在这篇文章中,我对 State 的优化机制做了说明。 一段因 @State 注入机制所产生的“灵异代码”

image

在本文提到的“任何可以在当前视图之外进行改动的 Source of Truth” ,主要是指例如 environment 、environmentObject 还有一些其他的符合 ObservableObject 的引用类型. 在你的实验中,onReceive 作为一个 source of truth ,在收到 notification 时,SwiftUI 对视图进行重新计算,在闭包中,你修改了一个没有在 body 中引入的 State 值,因为 State 的优化机制,因此,视图并不会重新计算。

qi3n commented 7 months ago

作者很用心 写的非常深入 比一般的教程有深度 很有帮助和启发

RokcyX commented 3 months ago

感谢分享,很有帮助

joeZheng3 commented 1 month ago

非常深入,感谢作者分享.