30

I have a list in a view (lets call it view A) where I push a view B via NavigationLink from view A and manipulate the CurrentSubjectValue to the initial view A. The moment the data is added and the didChangd.send(value) is dispatched to view A I get a warning that updating a cell that does not belong to a view. It seems that view A is removed from window which is unintuitive based on my previous UINavigationController behavior. Any idea?

View A (MainView)

struct MainView: View {

    @ObjectBinding var currentProfileIdStore = CurrentProfileIdStore.shared

    var body: some View {

        NavigationView {
            if (currentProfileIdStore.didChange.value == nil) {
                NavigationLink(destination: ProfilesView()){ Text("show profiles view")}
            } else {
                List {
                    Section {
                        ForEach(0..<1) { _ in
                            PresentationLink(destination: ProfilesView()) {
                                Text("Profiles")
                            }
                        }
                    }

                    Section {
                        ForEach(0..<1) { _ in
                            Text("Items")
                        }
                    }
                }.listStyle(.grouped)
            }
        }.navigationBarTitle(currentProfileIdStore.didChange.value ?? "unknown")

    }
}

Then profiles view is presented

struct ProfilesView : View {

    @ObjectBinding var profileManager = CurrentProfileIdStore.shared
    @ObjectBinding var profileProvider = ProfileProvider.shared

    var body: some View {

        NavigationView {

            List {
                Section {
                    ForEach(0..<1) { _ in
                        NavigationLink(destination: NewProfile()) {
                            Text("Add Profile")
                        }
                    }
                }


                Section {
                    ForEach(self.profileProvider.didChange.value) { profile in
                        VStack {

                            if profile.id == self.profileManager.didChange.value {
                                Image(systemName: "g.circle").transition(.move(edge: .top))
                            }

                            ProfileCellView(profile: profile)
                            Text(self.profileManager.didChange.value ?? "unknown").font(.footnote).color(.secondary)
                        }
                    }
                }

            }
            .navigationBarTitle("Profiles")
                .listStyle(.grouped)
        }
    }
}

and then we could add a new profile

struct NewProfile: View {

    @State var name: String = ""
    @State var successfullyAdded: Bool = false

    @ObjectBinding var keyboardStatus = KeyboardStatus()
    var profileProvider = ProfileProvider.shared

    var body: some View {

        NavigationView {
                VStack {
                    if self.successfullyAdded  {
                        Text("Successfully added please go back manually :)").lineLimit(nil)
                    }
                    Form {
                        Section(header: Text("Enter name")) {
                            TextField("Enter your name", text: $name)
                        }
                    }
                    if name.count > 3 {
                        Button(action: {
                            self.profileProvider.addProfile(new: Profile(name: self.name, id: UUID().uuidString)) {
                                assert(Thread.isMainThread)
                                self.successfullyAdded = true
                            }
                        }) {
                            Text("Add")
                        }.transition(.move(edge: .bottom))
                    }
                }.padding(.bottom, self.keyboardStatus.didChange.value)
        }.navigationBarTitle("Add Profile")

    }
}

and then there is provider

class ProfileProvider: BindableObject {

    enum Query {
        case all

        var filter: (Profile) -> Bool {
            switch self {
            case .all:
                return { p in true }
            }
        }
    }

    static var samples: [Profile] = []

    static var shared: ProfileProvider = {

        return ProfileProvider(query: .all)
    }()

    var didChange = CurrentValueSubject<[Profile], Never>([])

    private var query: Query?

    private init(query: Query? = nil) {

        self.query = query
        assert(Thread.isMainThread)

        dispatchDidChange()
    }

    func dispatchDidChange() {
        assert(Thread.isMainThread)
        if let valid = self.query {
            didChange.send(ProfileProvider.samples.filter {  valid.filter($0) })
        } else {
            didChange.send([])
        }
    }

    func addProfile(new: Profile, comp: () -> Void) {

        ProfileProvider.samples.append(new)
        comp()
        dispatchDidChange()
    }

keep in mind that multiple views share the same provider subject. so the issue happens when the new profile is added.

self.profileProvider.addProfile(new

there are two more issues, one that when back in mainView the button no longer works. Also when modally presented I don't yet know how to go back manually.

6
  • 1
    #1. It's a warning, right? The important question is - does it work as you expect it to? Remember, SwiftUI is barely in beta 3 of version 1! I get those warnings too. Hopefully, this will be improved in future betas. (1) To turn off these warnings, set OS_ACTIVITY_MODE to disable in your builds. Not necessarily recommending that - but it does get rid of noise. (2) If the behavior is not what you'd expect, post some code. So we can help.
    – user7014451
    Jul 14, 2019 at 14:02
  • #2. Could it be a timing issue? If so, look at a question I had answer Friday: stackoverflow.com/questions/57008251/…
    – user7014451
    Jul 14, 2019 at 14:03
  • Consider adding some code. A minimal example that shows us the error. in action Otherwise, it's all speculation. See stackoverflow.com/help/how-to-ask
    – kontiki
    Jul 14, 2019 at 14:13
  • 4
    I'm not using SwiftUI but I started seeing that warning in the console after I upgraded to Xcode 11. I'm seeing it on UITableViewControllers that are pretty stock. There were no errors before Xcode 11 and now they're there almost all the time. These are pretty bare bones view controllers. I certainly haven't made any changes to how the table view gets inserted into the view hierarchy. For now I'm choosing to ignore them. The warning is still there in Xcode 11.1. Oct 13, 2019 at 14:50
  • 2
    I'm also seeing this. Xcode 11.2.1 Dec 14, 2019 at 14:03

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.