Łukasz
Łukasz

Reputation: 805

Swift Combine and SwiftUI understanding needs corrections

I try do achieve something simple. In AppDelegate I need var vertices: [SCNVector3] = []. In @IBAction func getVertices(_ sender: Any) I can read file and assign new value to vertices. Simple and works. But when I try to pass value to SwiftUI View I have problems. If I define

@State var vertices: [SCNVector3] = []

func applicationDidFinishLaunching(_ aNotification: Notification) {
    ....
    let contentView = CloudView(data: $vertices)
    ....
    window.contentView = NSHostingView(rootView: contentView)
    ...
}

@IBAction func getVertices(_ sender: Any) {
    ...
    do {
        let readVertices: [SCNVector3] = try... // read file and convert to [SCNVector3]
        vertcices = readVertices // assign or not to assign, this is a question
        print (readVertices.count, vertices.count)
    }
    ...
}

and it prints:

3500 0

so, it never updates CloudView, vertices is always an empty array.

Could somebody explain me how I should do it in proper way?

Upvotes: 2

Views: 61

Answers (1)

Asperi
Asperi

Reputation: 258345

You cannot use @State outside of SwiftUI view context. In this scenario most appropriate will be to use ObservableObject, like

class VerticesStorage: ObservableObject {
   @Published var vertices: [SCNVector3] = []
}

then in AppDelegate

let verticesStorage = VerticesStorage()   // initialize property

func applicationDidFinishLaunching(_ aNotification: Notification) {
    ....
    let contentView = CloudView(data: verticesStorage) // inject reference
    ....
    window.contentView = NSHostingView(rootView: contentView)
    ...
}

@IBAction func getVertices(_ sender: Any) {
    ...
    do {
        let readVertices: [SCNVector3] = try... // read file and convert to [SCNVector3]

        verticesStorage.vertcices = readVertices // update here !!

        print (readVertices.count, vertices.count)
    }
    ...
}

and now in SwiftUI part

struct CloudView: View {
   @ObservedObject var data: VerticesStorage     // observable !!

   var body: some View {
     // present here
   }
}

Upvotes: 1

Related Questions