0

Can we do get and didSet together with lazy keyword. I have an array it fetch data from database (get) and another thing when that array will modify i will call delegate to reload data in didSet.

Its not working and not complain of any error.

  class CoreDataManager {
        func fetchUsers() -> [UserEntity] {
            var users: [UserEntity] = []
            do {
                users = try! context.fetch(UserEntity.fetchRequest())
            }catch {
                print("Fetch user Error,", error)
            }
            return users
        }
    }


    protocol UserControllerToViewModel: AnyObject {
        func reloadData()
    }


    class UserViewModel {
                
        private var manager = CoreDataManager()
        weak var delegate: UserControllerToViewModel?
// Here I want to get users and didset together with lazy keyword but its not working
        lazy var users: [UserEntity] = manager.fetchUsers() {
            didSet {
                delegate?.reloadData()
            }
        }
        
    }

Demo GitHub Project link: https://github.com/YogeshPateliOS/TableView_MVVM.git

Yogesh Patel
  • 1,893
  • 1
  • 20
  • 55

1 Answers1

2

As @EmilioPelaez said, the first time you access the lazy property you will be initialising it so the didSet won't be called.

This can be demonstrated by the following simplification of your example code:

func getData() -> [Int] {
   [1,2,3,4,5]
}

class UserViewModel {
   
   lazy var users = getData() {
      didSet {
         print("didSetting")
      }
   }
}

let vm = UserViewModel()

print(vm.users)

vm.users = [5,6,7,8]

print(vm.users)

This gives the output:

[1, 2, 3, 4, 5]
didSetting
[5, 6, 7, 8]

demonstrating that the didSet is only called when the property is being modified and not when being initialised.

EDIT:

To demonstrate that where the method that initialises the lazy var exists is irrelevant. Replace the above code with the below and the output is exactly the same; didSet won't be run on the first initialisation.

class Manager {
   func getData() -> [Int] {
      [1,2,3,4,5]
   }
}

class UserViewModel {
   let manager = Manager()
   lazy var users = manager.getData() {
      didSet {
         print("didSetting")
      }
   }
}

let vm = UserViewModel()
print(vm.users)
vm.users = [5,6,7,8]
print(vm.users)
flanker
  • 3,840
  • 1
  • 12
  • 20
  • Thank you for your time. In my case I cannot called manager.fetchUsers() as stored property because its run time variable. In your answer you direct assign value = getData(), in my case its not possible. any other approach? – Yogesh Patel May 05 '23 at 00:15
  • Sorry, don't understand your comment as you are doing this in your sample code. – flanker May 05 '23 at 09:10
  • If you download my code, I have an object of CoreDataManager() when I use manager.fetchUsers() as a get property and didSet to load ma table with lazy keyword. What you did is you use didSet that correct but you haven't use get property use you stored property. Is it make sense now? please let me know – Yogesh Patel May 05 '23 at 14:11
  • Your manager.fetchUsers() is an external method that synchronously returns an array and assigns it to users. getData() does exactly the same; it's an external method, not a stored property. – flanker May 05 '23 at 18:04
  • you can directly called your getData() but in my case you first need to create class object then you can use. how it is the same? – Yogesh Patel May 05 '23 at 19:15
  • It's irrelevant. It's just a method with signature `() -> [User]` i.e. a method returning an array. Where it exists (within reason) is irrelevant as long as it's accessible. But so you can see I've updated the answer with a similar approach, and the output is still the same, because all this is irrelevant. You still don't run `didSet` when you first iniaitlaise a variable. – flanker May 05 '23 at 20:24
  • Now it's really confusing me I run your code in the playground everything is working fine. I did the same thing in my question and project that I have added but it is not working for me. I totally understand for the first time, when I do the crud to array in my case didset is not calling, in your code it is working. I will check in detail. Thank you +1 – Yogesh Patel May 06 '23 at 00:21
  • Looking at your sample project I think you have more fundamental problems, too big to go into here, around how you are integrating the data into your views. I think you need to rethink how you are architecting the app. – flanker May 06 '23 at 12:40