繁体   English   中英

SwiftUI:将动态数据传递给内容视图后重绘

[英]SwiftUI: Redraw after passing dynamic data to content view

我有类似下面的内容,除了我在“ChildContentView”中有额外的动态手势。

我将如何强制子视图重绘/重新加载? 目前,任何动态内容绘制一次并且不会重新加载。 所有内容本质上都是静态的。

更新:需要使用let content: () -> Content而不是@State var content: () -> Content

// ChildContentView
struct ChildContentView<Content: View>: View {
    @State var content: () -> Content

    var body: some View {
        let dragGesture = DragGesture()...

        return Group {
            self.content()
        }.gesture(dragGesture)
    }
}
// ContentView
...
@State var changingList: [FooItem] = [] <-- This is dynamically changed.  Not reflected in this code snippet.

var body: some View {
    ZStack { 
        ChildContentView {
            List(changingList) { item in
                print("\(item)")
            }
        }
    }
}
...

你的麻烦是 State 属性包装器

struct ChildContentView<Content: View>: View {

@State var content: () -> Content

    var body: some View {
        let dragGesture = DragGesture()...

        return Group {
            self.content()
        }.gesture(dragGesture)
    }
}

它使内容“静态”(实际上你做到了:-))

让我们看看并尝试这个例子(复制 - 粘贴 - 在你的模拟器中运行)

import SwiftUI
struct Child<Content: View>: View {
    var content: () -> Content
    var body: some View {
        content()
    }
}

struct Item: Identifiable {
    let txt: String
    let id = UUID()
}

struct ContentView: View {
    @State var items = [Item(txt: "Alfa"), Item(txt: "Beta")]
    var body: some View {
        ZStack {
            Child {
                List(self.items) { (item) in
                    Text(item.txt)
                }
            }
            Button(action: {
                self.items.append(contentsOf: [Item(txt: "game"), Item(txt: "Delta")])
            }) {
                Text("Tap me to change items").padding().padding(.vertical, 50).background(Color.yellow)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

确保列表中的项目在内容更改时修改其id值。 基本上散列视觉内容以创建每个视觉状态的唯一值。

例如

struct FooItem: Identifiable {
  var id: UUID = UUID()
  var text: String = ""

  var visualID: String {
    return id.uuidString
      + "\(text.hashValue)"
  }

}

我猜当id没有改变时,内部ZStack缓存无法识别对象已经改变。

所以使用ForEach因为这就是我在我的代码中得到的(但List也有id )......

var body: some View {
    ZStack {
      ForEach(self.changingList, id: \.visualID) { item in
        SomeView(item: item)
          .onTapGesture {
            //blah blah
        }
      }
    }
}

我在这个确切的问题上犹豫了好几天,直到解决为止。

我刚接触 SwiftUI 一个月,所以我不完全理解为什么会这样。 但是,将变量设置为常量“让”直接通过更新传递视图内容。

更改自:

struct ChildContentView<Content: View>: View {
    @State var content: () -> Content

    var body: some View {
        let dragGesture = DragGesture()...

        return Group {
            self.content()
        }.gesture(dragGesture)
    }
}

对此:

struct ChildContentView<Content: View>: View {
    let content: () -> Content

    var body: some View {
        let dragGesture = DragGesture()...

        return Group {
            self.content()
        }.gesture(dragGesture)
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM