skip to Main Content

I’m working on a project where I need to listen to any changes in an array of objects. By changes I refer:

  1. Add/Remove element in the array
  2. Any change in the existing array elements

Here is the sample code,

enum DownloadState {
    case queued
    case completed
}

class DownloadTask: ObservableObject {
    var downloadState: DownloadState = .queued
}

class DownloadManager {
    var downloadTasks = [DownloadTask]()
}

In the above code, DownloadManager contains an array of DownloadTask. I want to listen to the changes when,

  1. A new DownloadTask instance is added into downloadTasks array
  2. An existing DownloadTask instance is removed from downloadTasks array
  3. The underlying DownloadState is changed for a particular DownloadTask in downloadTasks array

2

Answers


  1. Chosen as BEST ANSWER

    The approach that worked for us:

    1. Create a protocol to listen to any changes in the DownloadTask

    public protocol DownloadStateHandlerDelegate: AnyObject {
        func didUpdateDownloadState(title: String, downloadState: DownloadState)
    }
    

    2. Passed the delegate instance to the DownloadManager during initialization.

    class DownloadManager {
        private weak var delegate: DownloadStateHandlerDelegate?
        private var downloadTasks = [DownloadTask]()
    
        init(delegate: DownloadStateHandlerDelegate) {
            self.delegate = delegate
        }
    }
    

    3. Called the delegate method didUpdateDownloadState whenever the downloadState of a DownloadTask is updated.

    Example:

    class DownloadTask {
        @Published private var downloadState: DownloadState {
            didSet {
                self.delegate?.didUpdateDownloadState(title: self.title, downloadState: self.downloadState)
            }
        }
    }
    

  2. A possible approach is to make task a value type and manager as ObservableObject with published property for array of tasks, like

    struct DownloadTask {
        var downloadState: DownloadState = .queued
    }
    
    class DownloadManager: ObservableObject {
        @Published var downloadTasks = [DownloadTask]()
    }
    

    So requested changes can be observed either via @ObservedObject wrapper in SwiftUI view or via manager.$downloadTasks publisher in any other place.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search