SwiftUI: наблюдайте за изменениями свойств @Environment - PullRequest
3 голосов
/ 16 января 2020

Я пытался использовать оболочку свойства SwiftUI @Environment, но мне не удалось заставить ее работать так, как я ожидал. Пожалуйста, помогите мне понять, что я делаю неправильно.

В качестве примера у меня есть объект, который выдает целое число раз в секунду:

class IntGenerator: ObservableObject {
    @Published var newValue = 0 {
        didSet {
            print(newValue)
        }
    }

    private var toCanc: AnyCancellable?

    init() {
        toCanc = Timer.TimerPublisher(interval: 1, runLoop: .main, mode: .default)
            .autoconnect()
            .map { _ in Int.random(in: 0..<1000) }
            .assign(to: \.newValue, on: self)
    }
}

Этот объект работает, как и ожидалось, поскольку я вижу все целые числа, сгенерированные в журнале консоли. Теперь, допустим, мы хотим, чтобы этот объект был объектом среды, доступным для всех приложений и для кого угодно. Давайте создадим связанный ключ среды:

struct IntGeneratorKey: EnvironmentKey {
    static let defaultValue = IntGenerator()
}

extension EnvironmentValues {
    var intGenerator: IntGenerator {
        get {
            return self[IntGeneratorKey.self]
        }
        set {
            self[IntGeneratorKey.self] = newValue
        }
    }
}

Теперь я могу получить доступ к этому объекту следующим образом (например, из вида):

struct TestView: View {
    @Environment(\.intGenerator) var intGenerator: IntGenerator

    var body: some View {
        Text("\(intGenerator.newValue)")
    }
}

К сожалению, несмотря на то, что newValue является Свойство @Published Я не получаю никаких обновлений по этому свойству, а Text всегда показывает 0. Я уверен, что я что-то здесь упустил, что происходит? Спасибо.

1 Ответ

4 голосов
/ 16 января 2020

Environment дает вам доступ к тому, что хранится в EnvironmentKey, но не генерирует наблюдателя для его внутренних компонентов (ie. Вы будете уведомлены, если значение EnvironmentKey изменилось само, но в вашем случае это экземпляр и его ссылка, хранящаяся под ключом, не изменяется). Так что это нужно сделать вручную, если у вас есть издатель, как показано ниже

@Environment(\.intGenerator) var intGenerator: IntGenerator

@State private var value = 0
var body: some View {
    Text("\(value)")
        .onReceive(intGenerator.$newValue) { self.value = $0 }
}

и все работы ... протестированы с Xcode 11.2 / iOS 13.2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...