Как я могу инициализировать View Again в SwiftUI? - PullRequest
3 голосов
/ 16 апреля 2020

Я использую SwfitUI в своем проекте, и у меня есть NavigationView и список. Я нажимаю на ячейку после открытия подробного вида и нажимаю кнопку навигации назад. Я хочу удалить представление (это структура, в SwiftUI) после нажатия кнопки навигации назад. Потому что, если я снова нажму ту же ячейку или кнопку, это не инициализирует новое представление, оно показывает старое представление. Я хочу сделать refre sh эту точку зрения. Как это сделать?

Моя структура FirstView:

struct FirstView: View {

    @ObservedObject var viewModel: FirstViewModel

    var body: some View {
        List(self.viewModel.objects, id: \.id) { object in
            ZStack {
                DetailViewCell(object: object)
                NavigationLink(destination: DetailViewBuilder.make(object)) {
                    EmptyView()
                }.buttonStyle(PlainButtonStyle())
            }
        }
    }
}

Моя структура DetailView:

struct DetailView: View {

    @ObservedObject var viewModel: DetailViewModel

    var body: some View {
        ZStack(alignment: .top) {
            Color.mainBackground.edgesIgnoringSafeArea(.all)
            VStack {
                ZStack {
                    Image("Square")
                    Image(self.viewModel.currentImage)
                }
                Text(self.viewModel.currentText)
                    .padding()
                    .frame(alignment: .center)
                    .minimumScaleFactor(0.1)
                Spacer()
                Button(action: {
                    self.viewModel.pressedPlayOrPauseButton()
                }, label: {
                    Image(self.viewModel.isPlaying ? "Pause" : "Play").foregroundColor(Color("Orange"))
                }).padding()
            }
        }
    }
}

Прежде всего, я go до деталей нажав на ячейку в FirstView. Затем я возвращаюсь с кнопкой возврата. Я нажимаю на ячейку еще раз, чтобы узнать подробности go, но новый вид не открывается. Он показывает старый вид.

Прежде чем я забуду, мой класс Builder:

final class DetailViewBuilder {
    static func make(object: Something) -> DetailView {

        let viewModel = DetailViewModel(object: object)
        let view = DetailView(viewModel: viewModel)

        return view
    }
}

Примечание. Если я буду использовать Sheet Presented, он работает. Это создает новый вид. Но я хочу использовать NavigationLink. Спасибо.

Ответы [ 2 ]

3 голосов
/ 16 апреля 2020

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

С его помощью можно использовать следующую обертку для создания реального пункта назначения только тогда, когда body будет обработано (ie. явно во время навигации, по которому щелкнули в вашем случае)

Протестировано с Xcode 11.4 / iOS 13.4

struct DeferView<Content: View>: View {
    let content: () -> Content

    init(@ViewBuilder _ content: @escaping () -> Content) {
        self.content = content
    }
    var body: some View {
        content()          // << everything is created here
    }
}

и теперь ваш строитель

final class DetailViewBuilder {
    static func make(object: Something) -> some View {
        DeferView {
           DetailView(viewModel: DetailViewModel(object: object))
        }
    }
}
1 голос
/ 16 апреля 2020

SwiftUI инициализирует NavigationView ссылки с нетерпением, поэтому вы не можете полагаться на их инициализатор для запуска каждый раз. Если вы напишете пользовательский init () для DetailView

    init(viewModel: DetailViewModel) {
    self.viewModel = viewModel
    print("Initialising \(self)")
}

, вы увидите вывод строки для каждой навигационной ссылки при загрузке FirstView.

В зависимости от того, что вы хотите сделать, вы может реализовать замыкание .onAppear {} в DetailView, которое изменит данные при появлении представления. Немного сложно предложить примеры реализации, поскольку я не уверен, в чем конкретно заключается ваша цель.

Есть несколько интересных обсуждений по этому адресу: https://www.notion.so/Lazy-Loading-Data-with-SwiftUI-and-Combine-70546ec6aca3481f80d104cd1f10a31a

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

...