首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用UIViewRepresentable更新ObservableObject

如何用UIViewRepresentable更新ObservableObject
EN

Stack Overflow用户
提问于 2019-08-13 12:52:14
回答 3查看 9.3K关注 0票数 15

我正在努力学习如何与SwiftUI结合,并且我正在挣扎如何用ObservableObject (以前的BindableObject)更新我的视图(从UIKit)。问题是,显然,一旦updateUIView对象发送已更改的通知,@Published方法就不会触发。

代码语言:javascript
复制
class DataSource: ObservableObject {
    @Published var locationCoordinates = [CLLocationCoordinate2D]()
    var value: Int = 0

    init() {
        Timer.scheduledTimer(withTimeInterval: 3, repeats: true) { timer in
            self.value += 1
            self.locationCoordinates.append(CLLocationCoordinate2D(latitude: 52, longitude: 16+0.1*Double(self.value)))
        }
    }
}

struct MyView: UIViewRepresentable {
    @ObservedObject var dataSource = DataSource()

    func makeUIView(context: Context) -> MKMapView {
        MKMapView(frame: .zero)
    }

    func updateUIView(_ view: MKMapView, context: Context) {
        let newestCoordinate = dataSource.locationCoordinates.last ?? CLLocationCoordinate2D(latitude: 52, longitude: 16)
        let annotation = MKPointAnnotation()
        annotation.coordinate = newestCoordinate
        annotation.title = "Test #\(dataSource.value)"
        view.addAnnotation(annotation)
    }
}

如何将该locationCoordinates数组绑定到视图,即每次刷新时都会添加一个新的点?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-08-13 13:48:49

为了确保您的ObservedObject不会多次被创建(您只需要它的一个副本),您可以将它放在UIViewRepresentable之外

代码语言:javascript
复制
import SwiftUI
import MapKit

struct ContentView: View {
    @ObservedObject var dataSource = DataSource()

    var body: some View {
        MyView(locationCoordinates: dataSource.locationCoordinates, value: dataSource.value)
    }
}
class DataSource: ObservableObject {
    @Published var locationCoordinates = [CLLocationCoordinate2D]()
    var value: Int = 0

    init() {
        Timer.scheduledTimer(withTimeInterval: 3, repeats: true) { timer in
            self.value += 1
            self.locationCoordinates.append(CLLocationCoordinate2D(latitude: 52, longitude: 16+0.1*Double(self.value)))
        }
    }
}

struct MyView: UIViewRepresentable {
    var locationCoordinates: [CLLocationCoordinate2D]
    var value: Int

    func makeUIView(context: Context) -> MKMapView {
        MKMapView(frame: .zero)
    }

    func updateUIView(_ view: MKMapView, context: Context) {
        print("I am being called!")
        let newestCoordinate = locationCoordinates.last ?? CLLocationCoordinate2D(latitude: 52, longitude: 16)
        let annotation = MKPointAnnotation()
        annotation.coordinate = newestCoordinate
        annotation.title = "Test #\(value)"
        view.addAnnotation(annotation)
    }
}
票数 14
EN

Stack Overflow用户

发布于 2019-11-12 21:30:40

这个解决方案适用于我,但适用于EnvironmentObject https://gist.github.com/svanimpe/152e6539cd371a9ae0cfee42b374d7c4

票数 1
EN

Stack Overflow用户

发布于 2021-11-27 12:34:04

我将提供一个通用的解决方案,任何UI/NS视图表示使用组合。我的方法有性能上的好处。

  1. 创建一个可观察的对象,并使用@已发布的包装器包装所需的属性。
  2. 使用步骤3中的方法通过可表示的视图中的updateView方法注入所观察到的对象
  3. 用视图模型作为参数对所需的视图进行子类。创建一个addViewModel方法,并使用组合运算符/订阅服务器并将它们添加到可取消的。

注意--对环境对象非常有用。

代码语言:javascript
复制
    struct swiftUIView : View {
      @EnvironmentObject var env : yourViewModel
      ...
      ...
          UIViewRep(wm : env)
     }

    struct UIViewRep : UIViewRepresentable {

     var wm : yourViewModel
     
     func makeUIView {
      let yv = yourView()
      yv.addViewModel(wm)
      return yv
      }}

    class yourView : UIView {
     var viewModel : yourViewModel?
     var cancellable = Set<AnyCancellable>()
     ...
     ...
     func addViewModel( _ wm : yourViewModel) {
     self.viewModel = wm

      self.viewModel?.desiredProperty
          .sink(receiveValue: { [unowned self] w in
        print("Make changes with ", w)
       }).store(in: &cancellable)
      }
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57478134

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档