如何在SwiftUI中创建一个通用的PreferenceKey?

3

我想创建一个通用的PreferenceKey,但是我的代码中有两个问题。

首先,我需要为T定义(),以便像StringInt这样的普通类型可以使用String()Int()。因此,我需要逐成员初始化器以支持T

其次,Xcode抱怨我的PreferenceKey未遵循Equatable协议,而我已经实现了<T: Equatable>。如何解决这两个问题?谢谢。


struct ContentView: View {
    
    @State private var stringOfText: String = "Hello, world!"
    
    var body: some View {
        
        Text(stringOfText)
            .preference(key: CustomPreferenceKey.self, value: stringOfText)
            .onPreferenceChange(CustomPreferenceKey.self) { newValue in print(newValue) }
        
        
    }
}

struct CustomPreferenceKey<T: Equatable>: PreferenceKey {
    
    static var defaultValue: T { get { return T() } }
    
    static func reduce(value: inout T, nextValue: () -> T) { value = nextValue() }
    
}
1个回答

7

这里是一种可能的方法。经过测试,适用于 Xcode 12.4 / iOS 14.4。

protocol Initable {
    init()
}

extension String: Initable {
}

struct CustomPreferenceKey<T: Equatable & Initable>: PreferenceKey {
    typealias Value = T

    static var defaultValue: T { get { T() } }

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

struct ContentView: View {

    @State private var stringOfText: String = "Hello, world!"

    var body: some View {

        Text(stringOfText)
            .preference(key: CustomPreferenceKey<String>.self, value: stringOfText)
            .onPreferenceChange(CustomPreferenceKey<String>.self) { newValue in print(newValue) }
    }
}

为什么我们需要 typealias Value = T?即使不使用 Value,它也可以使用 T。 - ios coder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接