@EnvironmentObject with array of class

Dear all,


I am struggling with using ObservableObject in my app. In principle things work fine only view updates are not trigger when changing attributes of 'contacts.' Using 'cnt' in the same way, updates are indeed reflected in views - is there something particular I have to do with the FtContacts class to fix that?


class AppEnv: ObservableObject {

@Published var contacts = [FtContact]()

@Published var cnt: Int = 0

[...]


struct ContentView: View {

@EnvironmentObject var appEnv: AppEnv

[...]


Any idea what I am missing here?


Thanks everybody

Accepted Reply

Only reference I have is what I read or what I noticed myself as issues with List.


Looks like List are not really mature or stabilized in SwiftUI.


That will come for sure.

In the meantime, may be worth file a bug, that may help to track the problems (even though I imagine they already have hundreds of simular reports).


So, thanks for the feedback, don't forget to mark the thread as closed.

Replies

is there something particular I have to do with the FtContacts class to fix that?


ANd you don't even show how FtContacts is defined !?!

How do you want anyone to imagine what could be wrong ?


Please post comprehensive parts of code, if possible the whole file.


Coulkd you also use tool formatter <> to make code easier to read and reference ?

Like this:

class AppEnv: ObservableObject { 
    @Published var contacts = [FtContact]()
    @Published var cnt: Int = 0
[...]

struct ContentView: View {
    @EnvironmentObject var appEnv: AppEnv
[...]

Thanks for your reply - imagine a very generic class with a couple of attributes


class FtContact {
    private var identifierKey: String
    private var givenName: String
    private var familyName: String
[...]
    func getIdentifierKey() -> String {
        return identifierKey
    }


that are accessible through some getters. The AppEnv class has a function that changes the content of its @Published variables like this:


    func refreshAll() {
        contacts = db.selectContacts()
        contacts.sort(by: { $0.sortValue() < $1.sortValue() })
        cnt_refreshAll = cnt_refreshAll + 1
    }


One the view, cnd_refreshAll changes immediately but attributes of contacts are not displayed.

Could you show as well the contentView, where the refresh should occur.


What I understand:

- when you call refreshAll, youreload contcts.

- You expect that it will trigger an update in the view

- this update does not occur or is it just the contacts which are not updated ? Is cnt_refreshAll a field that is updated in the view as well ?

Thanks Claude31, you understand things correctly.


From ContentView I basically call a sub-view 'MainListView' that draws a List using the 'contacts' array by looping through it and calling another sub-view 'ListRowView' with a parameter 'contact'. This call (line 13) does not result in an update. If I add line 12 (displaying the same info directly) it updates as expected and even the info from the sub-view is updated (shown twice then). Just having line 13 without line 12, it does not update.


struct MainListView: View {

    @EnvironmentObject var appEnv: AppEnv
    
    var body: some View {
       
        List {
            
            ForEach(appEnv.contacts, id: \.self) { contact in
                NavigationLink(
                  destination: ContactDetailView(contact: contact)) {
                    Text("\(contact.getFirstLine())") <-- this works
                    ListRowView(contact: contact) <-- this doesn't
                }
[...]

struct ListRowView: View {
    
    var contact: FtContact
    
    var body: some View {
         
  Text(contact.getFirstLine())
        
[...]

There are issues with List.


In some cases, changing to a scrollView with a VStack solves the issue:



struct MainListView: View {

    @EnvironmentObject var appEnv: AppEnv
    
    var body: some View {
          ScollView {
             VStack {     // TRY ADDING THIS
             // TRY REMOVE THIS  List {

Thanks again - you brought me on the right track! Different combinations of VStack and List did not help but moving the code from the sub-view back into the main view did the trick. As a work-around that's fine but I would still be interested to learn some backgrounds on the issue with List.


Would you have a reference for that?

Only reference I have is what I read or what I noticed myself as issues with List.


Looks like List are not really mature or stabilized in SwiftUI.


That will come for sure.

In the meantime, may be worth file a bug, that may help to track the problems (even though I imagine they already have hundreds of simular reports).


So, thanks for the feedback, don't forget to mark the thread as closed.