Guy S
Guy S

Reputation: 620

SwiftUI Observable not being updated when using a variable

For some reason, when assigning an object of Observable to a variable and then changing it - the view won't update. but If I access it by its index directly - it will:

Won't work:

var people = self.mypeople.people[0]
people.name = 'test'

Does work:

self.mypeople.people[0].name = 'test'

My guess is something about references, but I'm not sure :(

Example code:

//: A UIKit based Playground for presenting user interface

import SwiftUI
import PlaygroundSupport
import Combine

struct Person: Identifiable{
    var id: Int
    var name: String

    init(id: Int, name: String){
        self.id = id
        self.name = name
    }

}

class People: ObservableObject{
    @Published var people: [Person]

    init(){
        self.people = [
            Person(id: 1, name:"Javier"),
            Person(id: 2, name:"Juan"),
            Person(id: 3, name:"Pedro"),
            Person(id: 4, name:"Luis")]
    }

}

struct ContentView: View {
    @ObservedObject var mypeople: People = People()

    var body: some View {
        VStack{
            ForEach(mypeople.people){ person in
                Text("\(person.name)")
            }
            Button(action: {
                var people = self.mypeople.people[0]
                // this howver works:
                // self.mypeople.people[0].name = 'Test'
                people.name="Jaime2"
            }) {
                Text("Change name")
            }
        }
    }
}


PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())

Upvotes: 2

Views: 1244

Answers (1)

Trai Nguyen
Trai Nguyen

Reputation: 829

Your guess is correct!!

People objet is reference type and Person object is value type.

From here I can check type of object by this code:

func isReferenceType(toTest: Any) -> Bool {
    return type(of: toTest) is AnyObject
}

isReferenceType(toTest: Person(id: 1, name:"Javier")) //false
isReferenceType(toTest: People()) //true

So that when you get person by this line var people = self.mypeople.people[0], it just get and create new Person (address of this object is difference with self.mypeople.people[0] object), so in this case you expect change your data in array, you must set self.mypeople.people[0] = people after change people.name

HERE for more details about Reference Type and Value Type

Upvotes: 2

Related Questions