【问题标题】:When do I need to implement the contents of `reduce`?什么时候需要实现`reduce`的内容?
【发布时间】:2021-08-09 06:42:11
【问题描述】:

使用this code 作为参考。

如果将代码注释掉,内容为空,然后运行,也会出现同样的行为。

struct SizePreferenceKey: PreferenceKey {
    typealias Value = CGSize
    static var defaultValue: Value = .zero

    static func reduce(value _: inout Value, nextValue: () -> Value) {
//        _ = nextValue() <-- comment out
    }
}

我对@9​​87654322@ 尝试了同样的操作,效果很好。

struct ViewOffsetKey: PreferenceKey {
    typealias Value = CGFloat
    static var defaultValue = CGFloat.zero
    static func reduce(value: inout Value, nextValue: () -> Value) {
//        value += nextValue() <-- comment out
    }
}

我必须将它写到conformprotocol,但即使内容为空,它似乎也可以工作。为什么是这样?我什么时候需要内容?

换句话说,onPreferenceChange 似乎在不更新value 的情况下工作正常。这是为什么呢?

【问题讨论】:

  • reduce 仅在您使用同一个键有多个视图时才相关。在您引用的两个示例中都没有发生这种情况。答案可能会在确实发生这种情况的情况下使用,这可能是答案包括reduce 的实现。

标签: swift swiftui


【解决方案1】:

reduce 用于处理兄弟视图的首选项值(即,同一级别容器中的视图使用相同的首选项键,因此它被一个接一个地调用,需要决定做什么 - reduce 给了我们一个机会)。

这是一个如何计算同级视图的共同大小的示例(基于您的偏好键)。如果您删除 reduce 的内容,则只会使用第一个呼叫偏好值(按设计)

演示是使用 Xcode 13 / iOS 15 准备的

extension CGSize {
    static func +=(lhs: inout CGSize, rhs: CGSize) {
        lhs.width += rhs.width
        lhs.height += rhs.height
    }
}

struct SizePreferenceKey: PreferenceKey {
    typealias Value = CGSize
    static var defaultValue: Value = .zero

    static func reduce(value: inout Value, nextValue: () -> Value) {
        value += nextValue()
    }
}

struct TestPrefReduce: View {
    @State private var size: CGSize = .zero

    var body: some View {
        VStack {
            Text("Common size: [\(Int(size.width)) x \(Int(size.height))]")
            Divider()
            Text("Title").font(.title)
                .background(GeometryReader {
                    Color.clear.preference(key: SizePreferenceKey.self,
                        value: $0.frame(in: .local).size)
                     })
            Text("Hello, World!").font(.headline)
                .background(GeometryReader {
                    Color.clear.preference(key: SizePreferenceKey.self,
                        value: $0.frame(in: .local).size)
                     })
        }
        .onPreferenceChange(SizePreferenceKey.self) {
              self.size = $0
        }
    }
}

【讨论】:

  • $0.size$0.frame(in: .local).size 有什么区别?我会认为那是一样的
猜你喜欢
  • 1970-01-01
  • 2012-02-23
  • 2012-09-16
  • 2014-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-10
  • 2010-12-29
相关资源
最近更新 更多