SwiftUI 中的记忆?

Posted

技术标签:

【中文标题】SwiftUI 中的记忆?【英文标题】:Memoization in SwiftUI? 【发布时间】:2020-03-27 20:09:45 【问题描述】:

我来自 React,我使用 useMemo 来确保不会经常执行某些计算。我如何在 SwiftUI 中做这样的事情?

考虑这个例子:

struct MyView: View 
    var records: [Record]

    var body: some View 
        Text("expensive summary: \(self.expensiveSummary)")
    

    var expensiveSummary: String 
        // based on records, return string
        // containing a summary of records

        return ""
    

有什么方法可以确保我的 expensiveSummary 仅在我的记录数组更改时被调用?

【问题讨论】:

我们可以假设父视图正在传入records 并且会发生变化。 【参考方案1】:

这是作为EquatableView 内置的。

struct MyView: EquatableView  ... 

这只会在 body 的属性(在本例中为 records)实际发生变化时重新计算 expensiveSummary,这将阻止重新评估 expensiveSummary

这不会避免对expensiveSummary insidebody 进行多次评估。如果您需要缓存此类信息,您通常应该创建一个局部变量(尽管有时函数构建器语法不允许这样做,除非将部分代码提取到单独的函数中),或者在init 中计算一个属性。

作为风格问题,我建议不要计算属性的评估成本过高。这令人困惑,因为属性语法通常表明该操作很便宜。相反,我建议这是一个函数或在 init 中计算一次。

【讨论】:

【参考方案2】:

我认为我们可以将包装视图创建为Equatable。 (也许,我们可以使用EquatableView.equatable() 修饰符吗?)

struct UseMemo<KeyType: Equatable, ViewType: View>: View, Equatable 
    let key: KeyType
    let content: (KeyType) -> ViewType

    var body: some View 
        content(key)
    
    
    static func ==(lhs: UseMemo, rhs: UseMemo) -> Bool 
        return lhs.key == rhs.key
    

struct MyView: View 
    @State var records: [Int] = (Array<Int>)(1...10000)
    @State var other = false

    var body: some View 
        VStack 
            Button("Update other", action:  self.other.toggle() )
            Text("Other: \(String(other))") // This will be called everytime

            Button("Update records", action:  self.records.append(1) )
            
            UseMemo(key: records)  keys in
                // This is not called even if updated "other"
                // This is called when updates "records"
                Text("expensive summary: \(expensiveSummary)")
            
            
            // This will be called everytime
            Text("expensive summary: \(expensiveSummary)")
        
    
    
    var expensiveSummary: String 
        String(records.randomElement()!)
    

以下内容对我有帮助。

SwiftUI — Why should you write as many custom views for better performance SwiftUI: prevent View from refreshing when presenting a sheet

【讨论】:

以上是关于SwiftUI 中的记忆?的主要内容,如果未能解决你的问题,请参考以下文章

如何知道 UIKit 视图控制器中的 swiftUI 事件? ||如何提供 swiftUI 和 uikit 之间的通信

SwiftUI 中的动画状态变化

SwiftUI:随机“调用中的额外参数”错误

如何将我的自定义 ButtonStyle 添加到 swiftui3 中的快捷方式 swiftui .buttonstyle() 属性

SwiftUI 中的@FetchRequest

SwiftUI:表单中的按钮