0

I need some help with this question please.

I am using SQLite.swift to store data in DB, I would like to fetch data only once when the application starts as it's a heavy operation. I need to be able to update / delete items from the user fields array in memory and display it accordingly in the DataScene.

The App contains a Tabbar at the bottom with 2 Tabs, Home and Data. The DataScene contains a list of all fields in the array. When an item in the user fields array has been updated or deleted from a Child view. The list in the DataScene needs to reflect that update.

The userFields array is defined in the TabBarScene and fetches the data from SQL just once because its declared as a lazy var in the Account object.

The sample code below works fine except the problem I have is when I switch between tabs. I need to be able to maintain the state of the array even when I switch between tabs so it keeps displaying the correct data, at the moment when you switch between tabs it displays the original records of the array.

Is this a 2 way binding issue? or do I need to use NSCache? I hope it's a simple issue. I hope I have provided enough information to the issue, otherwise please let me know. Thank you.


class Account {
    lazy var userFields: [UserField] = {        // Lazy var, fetches once
        UserField.fetchAll()
    }()
}

extension TabBarScene {
    class TabBarViewModel: ObservableObject {
        @Published var userFields: [UserField]
        init() {
            account = sessionService.account
            userFields = account.userFields     // Instantiated once
        }
    }
}

extension DataScene {
    class DataViewModel: ObservableObject {
        @Binding var userFields: [UserField]
        init(_ userFields: Binding<[UserField]>) {
            _userFields = userFields
        }
        
        func fetchData() {
            userFields = account.userFields
        }
    }
}

extension FieldForm {
    class FieldViewModel: ObservableObject {
        @Binding var userFields: [UserField]
        
        init(muserFields: Binding<[UserField]>) {
            self._userFields = userFields
        }
        
        func deleteTapped() {
            guard let label  else { return }
            let record = userFields.filter { $0.id == account.id && $0.name == name }.first
            record?.delete()
            if let record {
                userFields.remove(record)
            }
        }
    }
}

extension HomeScene {
    class HomeViewModel: ObservableObject {
        init() {
            // Display another View
        }
    }
}

Wael
  • 489
  • 6
  • 19
  • Don’t use `@Binding` outside a view. Make sure you have a single source of truth for your array. – Joakim Danielson Jun 13 '23 at 06:38
  • Thank you Joakim for response, which @Binding do you refer to please? I am just a little confused about my problem at the moment. If you could provide a sample code would be appreciated. – Wael Jun 13 '23 at 06:41
  • Both of them since they are in classes and not View’s – Joakim Danielson Jun 13 '23 at 06:43
  • Use TabBarViewModel as an EnvironmentObject in all your views that need to access the array and do not have a reference to it in any other of your view model classes. – Joakim Danielson Jun 13 '23 at 06:48
  • I have just tried removing the binding but if I remove the Binding it will not update a display list in the data scene. so If I delete an item from the array the display list in the DataScene needs to be updated and removed. – Wael Jun 13 '23 at 06:51
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/254060/discussion-between-wael-and-joakim-danielson). – Wael Jun 13 '23 at 11:12

0 Answers0