0

我创建了一个属性包装器,我想在其中插入一些逻辑,并且“set”值正在做正确的事情,但文本字段并未使用所有大写文本进行更新。文本字段不应该显示所有大写文本还是我误解了它是如何工作的?

这也是一个人为的例子,我的最终目标是在属性包装器中插入更多的逻辑,我只是​​使用大写的例子来让它工作。我在互联网上搜索了所有内容,但没有找到可行的解决方案。

import SwiftUI
import Combine

struct ContentView: View {
    @StateObject var vm = FormDataViewModel()

    var body: some View {
        Form {
            TextField("Name", text: $vm.name)
        }
    }
}

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

class FormDataViewModel: ObservableObject {
    @Capitalized var name: String = ""
}

@propertyWrapper
public class Capitalized {
    @Published var value: String

    public var wrappedValue: String {
        get { value }
        set { value = newValue.uppercased() } //Printing this shows all caps
    }

    public var projectedValue: AnyPublisher<String, Never> {
        return $value
            .eraseToAnyPublisher()
    }

    public init(wrappedValue: String) {
        value = wrappedValue
    }
}
4

2 回答 2

1

SwiftUI 监视 or中@Published的属性,并根据它们的更改触发 UI 更新。@StateObject@ObservedObject

但它并没有深入到ObservableObject. 您FormDataViewModel没有任何@Published属性。


您可以做的一件事是模拟@Published对价值变化的影响。

class FormDataViewModel: ObservableObject {
    @Capitalized var name: String = ""
    private var nameObserver: AnyCancellable?

    init() {
        nameObserver = _name.$value.sink {_ in
            self.objectWillChange.send()
        }
    }
}

请试试。

于 2020-08-18T01:00:00.893 回答
1

这可以通过@Published看起来更简单、更可靠的标准来完成。

这是一个解决方案。使用 Xcode 12 / iOS 14 测试。

class FormDataViewModel: ObservableObject {
    @Published var name: String = "" {
        didSet {
            let capitalized = name.uppercased()
            if name != capitalized {
                name = capitalized
                objectWillChange.send()
            }
        }
    }
}
于 2020-08-18T03:55:36.673 回答