Обновление списка SwiftUI

Я пытаюсь обновить этот список всякий раз, когда нажимаю на ссылку NavLink

NavigationView {
    List(feed.items.indices, id:\.self) { i in
        NavigationLink(destination: ListFeedItemDetail(idx: i).environmentObject(self.feed)) {
            ListFeedItem(item: self.$feed.items[i])
        }
    }
}

Список состоит из массива внутри объекта окружения. Проблема: он обновляется только тогда, когда я переключаюсь на другую вкладку или закрываю приложение, которое я использовал раньше в модальном представлении, и оно там работало. (Я сделал это с помощью .onAppear) Есть идеи?

Пример

Проблема: когда вы нажимаете на элемент в списке и нажимаете кнопку переключения, EnvironmentObject изменяется, но это изменение отражается только тогда, когда я меняю вкладку и снова меняю ее

import SwiftUI
import Combine

struct TestView: View {

    @State var showSheet: Bool = false
    @EnvironmentObject var feed: TestObject
    func addObjects() {
        var strings = ["one","two","three","four","five","six"]
        for s in strings {
            var testItem = TestItem(text: s)
            self.feed.items.append(testItem)
        }
    }

    var body: some View {
        TabView {
            NavigationView {
                List(feed.items.indices, id:\.self) { i in
                    NavigationLink(destination: detailView(feed: self._feed, i: i)) {
                        HStack {
                            Text(self.feed.items[i].text)
                            Text("(\(self.feed.items[i].read.description))")
                        }
                    }
                }
            }
                .tabItem({ Text("Test") })
                .tag(0)

            Text("Blank")
                .tabItem({ Text("Test") })
                .tag(0)
        }.onAppear {
            self.addObjects()
        }
    }
}

struct detailView: View {
    @EnvironmentObject var feed: TestObject
    var i: Int
    var body: some View {
        VStack {
            Text(feed.items[i].text)
            Text(feed.items[i].read.description)
            Button(action: {  self.feed.items[self.i].isRead.toggle() }) {
                Text("Toggle read")
            }
        }
    }
}

final class TestItem: ObservableObject {
    init(text: String) {
        self.text = text
        self.isRead = false
    }
    static func == (lhs: TestItem, rhs: TestItem) -> Bool {
        lhs.text < rhs.text
    }
    var text: String
    var isRead: Bool

    let willChange = PassthroughSubject<TestItem, Never>()
    var read: Bool {
        set {
            self.isRead = newValue
        }
        get {
            self.isRead
        }
    }
}

class TestObject: ObservableObject {
    var willChange = PassthroughSubject<TestObject, Never>()

    @Published var items: [TestItem] = [] {
        didSet {
            willChange.send(self)
        }
    }
}

person nOk    schedule 30.08.2019    source источник
comment
Не могли бы вы разместить больше кода? Может быть, достаточно, чтобы мы продублировали вашу проблему?   -  person dfd    schedule 30.08.2019
comment
Я добавил пример (мой код слишком разбросан для этого), но проблема та же. Несмотря на то, что я обновляю свой environmentObject, он не обновляет представление   -  person nOk    schedule 30.08.2019
comment
@nOk В вашем примере кода вы передаете feed в инициализатор подробного представления, тогда как вы должны передавать его как объект среды, подобный этому - detailView(i: i).environmentObject(self.feed). Я не уверен, что это полностью решит проблему, но я заметил это, просматривая ваш код.   -  person graycampbell    schedule 30.08.2019


Ответы (1)


У меня была аналогичная проблема, это тот хак, который я придумал.

В вашем "TestView" объявите:

@State var needRefresh: Bool = false

Передайте это в пункт назначения "detailView", например:

NavigationLink(destination: detailView(feed: self._feed, i: i, needRefresh: self.$needRefresh)) {
     HStack {
            Text(self.feed.items[i].text)
            Text("(\(self.feed.items[i].read.description))")
     }.accentColor(self.needRefresh ? .white : .black)
 }

Обратите внимание на «.accentColor (self.needRefresh? .White: .black)», чтобы принудительно выполнить обновление при изменении «needRefresh».

В пункте назначения "detailView" добавьте:

@Binding var needRefresh: Bool

Затем в "detailView" в действии Button добавьте:

self.needRefresh.toggle()
person workingdog    schedule 30.08.2019
comment
Это сработало: D Спасибо за помощь. Вы думаете, что это ошибка? Я обязательно подам отчет об ошибке. В этом нет необходимости ^^ - person nOk; 31.08.2019
comment
то, что я сделал, - настоящий хакер. Должен быть способ получше. Это ошибка? Я не знаю. - person workingdog; 01.09.2019
comment
Я пробовал что-то и обнаружил, что проблема в том, что вы / я используете TestItem как класс. Это должна быть структура. И все будет работать без взлома. - person workingdog; 01.09.2019
comment
похоже, это не запускает обновление для меня - person Quinn; 25.10.2019
comment
не могли бы вы поделиться своими настройками. Также вы имеете в виду взлом или код TestObservedObject. Я использую Xcode 11 и Xcode 11.2 beta 2 с целью IOS 13, и у меня это хорошо работает. - person workingdog; 27.10.2019