如何在 SwiftUI 中创建通用 PreferenceKey?

use*_*ser 3 swift swiftui

我想制作一个Generic PreferenceKey,但我的代码有两个问题。

首先,我需要为T定义(),以便使用StringInt作为String()Int()等普通类型,因此我需要T成员初始化程序

第二个 Xcode 抱怨我的PreferenceKey不符合Equatable,而我做到了! <T:可等量>

我该如何解决这2个问题?谢谢


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) }
        
        
    }
}
Run Code Online (Sandbox Code Playgroud)
struct CustomPreferenceKey<T: Equatable>: PreferenceKey {
    
    static var defaultValue: T { get { return T() } }
    
    static func reduce(value: inout T, nextValue: () -> T) { value = nextValue() }
    
}
Run Code Online (Sandbox Code Playgroud)

Asp*_*eri 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) }
    }
}
Run Code Online (Sandbox Code Playgroud)