SwiftUI нажмите кнопку, чтобы подписаться - PullRequest
0 голосов
/ 15 января 2020

У меня есть несколько представлений, которые содержат одну и ту же кнопку с различным содержанием. Из-за этого я сделал ContainerView, в котором находится общий Button макет, и есть место для универсального c ContentView.

Я хочу, чтобы ContentView отвечал, когда ContainerView кнопка нажата.

Используя UIKit, я бы держал ссылку на ContentView в ContainerView и вызывал функцию на нем при нажатии кнопки. Однако, поскольку SwiftUI имеет все представления как структуры, contentView копируется, когда помещается в ContainerView body. Таким образом, ссылка и показанный ContentView различны, и я не могу отправить подпредставлению сообщение.

Код:

struct ContainerView: View {
    let contentView = ContentView()

    var body: some View {
        Group {
            /// When this button is tapped, I would like to send a message to the `ContentView`.
            Button(action: self.reset, label: { Text("RESET") })
            /// Unfortunately, this seemes to send a copy of the `contentView`. So I am unable to send the
            /// corrent struct a message.
            ///
            /// How can I send a subview a message from the superview?
            self.contentView
        }
    }

    func reset() {
        self.contentView.reset()
    }
}

struct ContentView: View {
    @State private var count: Int = 0

    var body: some View {
        Group {
            Text("Count: \(self.count)")
            Button(action: self.increment, label: { Text("Increment") })
        }
    }

    func increment() {
        self.count += 1
    }

    /// When this is called from the `ContainerView`, it is accessing a different ContentView 
    /// struct than is being displayed.
    func reset() {
        self.count = 0
    }
}

Итак, вопрос: как я могу отправить сообщение на & запустить какой-нибудь код в ContentView, когда нажата кнопка в ContainerView?

1 Ответ

2 голосов
/ 15 января 2020

Вместо того, чтобы пытаться сохранить ссылку на подпредставление, почему бы не сделать связь между ними? В вашем примере это может быть связано с привязкой к количеству.

struct ContainerView: View {
    @State private var count = 0

    var body: some View {
        // Your Button wrapping the ContentView
        ContentView(count: $count)
    }

    func reset() {
        self.count = 0
    }
}


struct ContentView: View {
    @Binding var count: Int

    // ContentView's body
}

Когда ContainerView сбрасывает счет, привязка обновит дочерний элемент.

РЕДАКТИРОВАТЬ: я вижу ваши комментарии о желании ContentView управлять сбросом c. Как насчет попытки воспроизвести некоторые функциональные возможности, такие как NavigationLink, где задается isActive: bool, а затем сбрасывается системой навигации?

В вашем случае вы можете попробовать следующее:

struct ContainerView: View {
    @State private var shouldReset: Bool = false

    var body: some View {
        // Your Button wrapping the ContentView
        ContentView(shouldReset: $shouldReset)
    }

    func reset() {
        self.shouldReset = true
    }
}


struct ContentView: View {
    @Binding var shouldReset: Bool {
        didSet {
            if shouldReset {
                // Call your reset logic here
            }
            shouldReset = false
        }
    }

    // ContentView's body
}

Ваш ContentView будет знать об этом изменении, мы увидим его как отдельное "состояние", а затем это состояние будет сброшено после завершения действия.

Вероятно, это не идеальное решение, но мне кажется, что оно повторяет шаблон, показанный некоторыми компонентами SwiftUI первой стороны.

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