4

I am using beta 4 Xcode and simply have a list of string items that is modally presented from a main view.

    var body: some View {
        NavigationView {
            List {
                Section() {
                    Button(action: {
                        self.shouldShowModal = true
                        self.areasModal = true
                        self.accountsModal = false
                    }) {
                        Text("Areas")
                    }
                }
            }
        }
        .sheet(isPresented: $shouldShowModal, onDismiss: {
            // on dismiss
        }) {
            if self.accountsModal {
                Text("Accounts")
            } else if self.areasModal {
                AreaListView()
            } 
        }
    }

in the AreaListView I have the following

class MockModel: BindableObject {

    struct MockItem: Identifiable {
        var id: String
    }

    var willChange = PassthroughSubject<Void, Never>()

    var items: [MockItem] = [] {
        willSet {
            self.willChange.send()
        }
    }

    init() {
        self.performFetch()
    }

    func performFetch() {
        DispatchQueue.main.async { [weak self] in
            self?.items = [MockItem(id: "first"), MockItem(id: "fjirst"), MockItem(id: "fiklkrst"), MockItem(id: "fijlkrst")]
        }
    }

    deinit {
        print("deinit")
    }
}

in perform fetch function I simulate cases where the model does a background process and then I need to return to the main thread.

and in the AreasListView I have

struct AreaListView: View {
    @ObjectBinding var model = MockModel()
    var body: some View {
        NavigationView {
            List {
                ForEach(model.items) { (item) -> Text in
                    return Text(item.id)
                }
            }
        }
    }
}

it works just fine when I open the areas for the first time but the second time it stops populating the list. I observed then having the async removed from the performFetch() everything works as expected. I also observe that deinit is called not when the modal(sheet) is closed (by pulling down) but when I open the AreasListView for the second time. Could someone explain why the dispatch async causes Mal-function and also why deinitiation happens upon second opening of the AreasListView? many thanks,

p.s. also when adding the dispatch async to my model I see the following errors in the console log

=== AttributeGraph: cycle detected through attribute 18 ===
=== AttributeGraph: cycle detected through attribute 18 ===
=== AttributeGraph: cycle detected through attribute 104 ==

I have also tried the following not using the dispatch queue

    func getItem() -> Future<[MockItem], Never> {
        return Future { promise in
            let t = [MockItem(id: "first"), MockItem(id: "fjirst"), MockItem(id: "fiklkrst"), MockItem(id: "fijlkrst")]
            promise(.success(t))
        }
    }

    func performFetch() {
        temp = getItem().eraseToAnyPublisher().receive(on: RunLoop.main)
            .sink(receiveValue: { [weak self] (items) in

                self?.items = items
            })
    }
Congruent Tech. UG
  • 1,408
  • 2
  • 12
  • 21

0 Answers0