Home > Software engineering >  Update collection view after computing view models in background
Update collection view after computing view models in background

Time:05-11

I receive data items from my API, on a specific serial queue, that I use to calculate the view models to display in a collection view. The simplified code is:

var viewModels: [ViewModel] = []    // read and written on main queue
var _viewModels: [ViewModel] = []   // written in background, read in main queue

func didReceive(items: [Item]) {
    // called on the same background serial queue
    _viewModels = items.map { ViewModel($0) }
    DispatchQueue.main.async {
        self.viewModels = self._viewModels
        self.updateCollectionView {
            // UI update has finished
        }
    }
}

didReceive can be called at any time. _viewModels is written always on the same background queue. After that I switch to main queue to cache the computed view models and use it in data source for displaying.

Can self.viewModels = self._viewModels lead to crashes? Do I have to use some kind of locking mechanism? If yes, how does it work when main thread is involved?

CodePudding user response:

Crashes not necessarily, but this can lead to inconsistency. As _viewModels is declared outside the scope of didReceive, it is a shared resource that can be modified each time you enter didReceive. After dispatching this to the main thread, some other thread can enter in didReceive and change your value. So when you assign it to self.viewModels, you would get the "second" value.

I believe that declaring _viewModels inside didReceive would fix your issue, as you would have a reference for each run of didReceive:

var viewModels: [ViewModel] = []    // read and written on main queue

func didReceive(items: [Item]) {
    // called on the same background serial queue
    let _viewModels = items.map { ViewModel($0) }
    DispatchQueue.main.async {
        self.viewModels = _viewModels
        self.updateCollectionView {
            // UI update has finished
        }
    }
}

If you are not allowed to do this, try taking a look at Actors: https://www.avanderlee.com/swift/actors/

  • Related