Как повторно инициализировать классы в SwiftUI NavigationView - PullRequest
0 голосов
/ 21 октября 2019

У меня есть два вида - MasterView и DetailView. При открытии DetailView я инициализирую новый класс, который отслеживает данные о представлении (в реальной реализации представление подробностей включает в себя игру).

Однако, когда я нажимаю кнопку возврата из DetailView, чтобы вернуться кMasterView, а затем нажмите кнопку, чтобы вернуться к DetailView, мой класс не изменился. Однако я хотел бы повторно инициализировать новую копию этого класса (в моем случае, чтобы перезапустить игру) всякий раз, когда я перехожу из MasterView в DetailView.

Я сконцентрировал проблему в этом коде:

import SwiftUI
import Combine

class Model: ObservableObject {
    @Published var mytext: String = "mytext"
}

struct MasterView: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: DetailView(model: Model())) {
                Text("press me")
            }
        }
    }
}

struct DetailView: View {
    @ObservedObject var model: Model = Model()

    var body: some View {
        TextField("Enter here", text: $model.mytext)
    }
}


struct MasterView_Previews: PreviewProvider {
    static var previews: some View {
        MasterView()
    }
}

Я хотел бы создавать новый экземпляр Model каждый раз, когда я нажимаю NavigationLink для подробного просмотра, но кажется, что он всегда ссылается на один и тот же оригинальный экземпляр - я вижуэто путем ввода изменения в текстовое поле DetailView, которое сохраняется, если я возвращаюсь назад и вперед снова.

Есть ли способ сделать это?

1 Ответ

1 голос
/ 22 октября 2019

Основываясь на ваших комментариях - и поправьте меня, где не так - вот как я это настрою.

Ваши потребности:

  • Базовый класс. Назовите это MasterView, «настройки», «состояние просмотра», как угодно. Это где все начинается.
  • "текущая игра" .... ну, это могут быть struct, class, даже свойства в ObservableObject.

Я думаю, вот и все. Иерархически ваша модель может быть:

ViewState

... Player

...... Свойства, включая идентификатор и историю

... Текущая игра

...... Свойства, включая сложность

Обратите внимание, я изменил некоторые имена и сейчас очень расплывчато по свойствам. Дело в том, что вы можете инкапсулировать все этого в ObservableObject, создать его «EnvironmentObject» и заставить все ваши представления SwiftUI «реагировать» на изменения в нем.

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

(1) Создайте свой ObservableObject. Для необходимо , чтобы (a) быть объектом класса и (b) соответствовать протоколу ObservableObject. Вот простой:

class ViewState : ObservableObject {
    var objectWillChange = PassthroughSubject<Void, Never>()
    @Published var playerID = ""  {
        willSet {
            objectWillChange.send()
        }
    }
}

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

(2) Создавать ViewState один раз мин вашей среде. В SceneDelegate:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = UIHostingController(rootView: ContentView()
            .environmentObject(ViewState())
        )
        self.window = window
        window.makeKeyAndVisible()
    }
}

Обратите внимание, что здесь добавляется одна строка и ViewState создается один раз.

(3) Наконец, в any Представление SwiftUI, которому необходимо знать состояние вашего представления, свяжите его, добавив одну строку кода:

@EnvironmentObject var model: ViewState

Если вы хотите, вы можете делать практически все в вашей модели (ViewState) из создание экземпляра новой игры, отметка чего-либо, что приводит к модальному всплывающему окну, добавление игрока в массив, что угодно.

Главное, что я надеюсь объяснить, - нет необходимости создавать экземпляр второе состояние просмотра - скорее создайте экземпляр второго игрового экземпляра внутри вашего единственного состояния просмотра.

Опять же, если я далеко от ваших потребностей, дайте мне знать - яс удовольствием удалю мой ответ. Удачи!

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