SwiftUI: почему измененное свойство моих данных не обновляет пользовательский интерфейс?

#swift #swiftui #observedobject

#swift #swiftui #observedobject

Вопрос:

У меня следующая модель данных:

 class MyImage: : Identifiable, Equatable, ObservableObject {
    let id = UUID()

    var path: String
    @Published var coordinate: CLLocationCoordinate2D?
}

class MyImageCollection : ObservableObject {
    @Published var images: [MyImage] = []
    @Published var selection: Set<UUID> = []

}

extension Array where Element == MyImage {
    func haveCoordinates() -> Array<MyImage> {
        return filter { (image) -> Bool in
            return image.coordinate != nil
        }
    }
}
 

Я использую коллекцию в представлениях следующим образом:

 # Top View

@StateObject var imageModel: MyImageCollection = MyImageCollection()

# Dependend Views

@ObservedObject var imageModel: MyImageCollection

 

Итак, в моем SwiftUI всякий раз, когда я добавляю новый экземпляр myImage через imageCollection.images.append(anImage) , все работает отлично, и любое представление обновляется соответствующим образом, также обновляется любое представление, использующее imageCollection.haveCoordinates() . Но я также хочу, чтобы любые представления обновлялись, когда я изменяю свойство изображения, например imageCollection.images[0].coordinate = someCoordinate . В настоящее время это не работает.

Какие-либо подсказки?

Ответ №1:

Ваши подвиды должны непосредственно наблюдать за вашим классом ‘myImage’, который будет соответствующим образом обновлен. Передайте ваши экземпляры ‘myImage’ непосредственно в наблюдаемую объектную переменную. Вот как это может выглядеть…

 ForEach(collection.images) { myImage in
   YourSubView(image: myImage)
}
 

Где параметр изображения передается наблюдаемому свойству объекта в вашем подвиде.

Ответ №2:

Переключите @ObservedObject @EnvironmentObject на DependantView и инициализируйте DependentView().environmentObject(imageModel) . Документация Apple.Это соединяет два экземпляра.

Кроме того, если вы хотите наблюдать за каждым MyImage , вам нужно создать MyImageView объект, который наблюдает за ним напрямую

 struct MyImage: View{
    @ObservedObject var myImage: MyImage
    //Rest of code
}
 

Ответ №3:

Спасибо за ваши ответы, очень признателен. Я пытался создать вложенное представление со ссылкой на объект также как ObservableObject, но потерпел неудачу, потому что я использовал MapAnnotation и инициализировал coordinate свойство. Нужно подробно разобраться, в чем здесь разница, документация от Apple не очень помогает сразу увидеть какую-либо разницу. Сейчас я использую какой-то обходной путь, «аннулируя» экземпляр myImage с установкой нового UUID:

 class MyImage: : Identifiable, Equatable, ObservableObject {
    var id = UUID()

    var path: String
    @Published var coordinate: CLLocationCoordinate2D? {
        didSet {
            id = UUID()
        }
    }
}