1

I was looking for an example for a DataStore in SwiftUI and found this example.

import SwiftUI
import Combine

class MyDatabase: ObservableObject {
    let didChange = PassthroughSubject<MyDatabase, Never>()

    var contacts: [Contact] = [
        Contact(id: 1, name: "Anna"), Contact(id: 2, name: "Beto"),
        Contact(id: 3, name: "Jack"), Contact(id: 4, name: "Sam")
    ] {
        didSet {
            didChange.send(self)
        }
    }

    struct Contact: Identifiable{
        var id: Int
        var name: String
    }
}

struct ContactsList: View {
    @EnvironmentObject private var database: MyDatabase

    var body: some View {
        NavigationView {
            List($database.contacts) { contact in
                NavigationLink(destination: ContactDetail(contact: contact)) {
                    Text(verbatim: contact.value.name)
                    //here Error 1: Types of expression....
                }
            }
            .navigationBarTitle(Text("Contacts"))
        }
    }
}

struct ContactDetail: View {
    @Binding var contact: MyDatabase.Contact

    var body: some View {
        VStack {
            TextField($contact[\.name])
                .textFieldStyle(.roundedBorder)
                .font(.title)
                .padding()
            //here Error 2: Types of expression....
            Spacer()
        }
        .navigationBarTitle(Text("Edit"), displayMode: .inline)
    }
}

However, after testing it, I got the below error multiple times:

Type of expression is ambiguous without more context

I also tried following tutorial for the same solution https://mecid.github.io/2019/07/03/managing-data-flow-in-swiftui/ but I got the same errors. Did anything changes regarding the Bindings in the latest beta? Im running Beta 6

vapcguy
  • 7,097
  • 1
  • 56
  • 52
  • I'm seeing a few warning signs, most from *beta 4 or 5*. Background: certain *warnings* in these betas have now turned into *errors*. (I don't think this is your issue.) But... where is `@Published`? Why is an `@ObservableObject` called `MyDatabase` using a `@Binding`, and that binding is to `MyDatabase.Contact`? Nothing *major* changed with `ObservableObject` in beta 6, but it sure changed in earlier betas. Did this code ever work? –  Aug 23 '19 at 19:46

1 Answers1

1

It seems that you are using ObservableObject like a BindableObject. The BindableObject is replaced from beta 4 (?).

BindableObject is replaced by the ObservableObject protocol from the Combine framework.

The didChange changed in favour of objectWillChange and he should be called inside the willChange observer.

To avoid repeating yourself the @Published attribute synthesizes the willChange for you.

You can manually conform to ObservableObject by defining an objectWillChange publisher that emits before the object changes. However, by default, ObservableObject automatically synthesizes objectWillChange and emits before any @Published properties change.

class User: ObservableObject {

    @Published var name: String = ""
    @Published var email: String = ""

}

And use the @ObservedObject if you want a binding of your ObservableObject:

struct MyView: View {

    @ObservedObject var user: User = User()

    var body: some View {
        TextField("Name", text: $user.name)
    }

}

If you continue to have problem because you are using @EnvironmentObject try to look at: Change to @Published var in @EnvironmentObject not reflected immediately

Giuseppe Sapienza
  • 4,101
  • 22
  • 23