Making a TableViewDataSource more independent of the data it utilizes
My concern is that my TableViewDataSource is too tightly coupled with having to know about how my Conductor class functions, and I could like to decouple some of the logic.


Create a protocol which defines the data in the form that the data source needs. This will separate the requirements of the data from the implementation of the class providing the data, which would give you flexibility to change the behaviour of the Orchestra object without also having to change the data source. 

The orchestra object should implement the protocol and provide the data in the required format. You can use a class extension on the orchestra or conductor to add the required code.


  Is calling the Singleton to populate my data source ok? And if not, what are better ways to make my TableViewDataSource more independent? 


Using Singletons often leads to problems. It would be better to follow the dependency inversion principle and pass an instance of the conductor to the data source. From the code you have shown you only seem to be using the orchestra, and so the conductor itself is not needed.

Example

The example below shows how to:


Define a protocol.
Use a class extension to have a class conform to the protocol.
Update the data source to use the protocol instead of the concrete class.
Pass the orchestra instance into the data source.


1. Define a protocol:

protocol Performers {
    var numberOfSections: Int {
        get
    }
    func numberOfPerformers(inSection: Int) -&gt; Int
    func performer(atIndex: Int, inSection: Int) -&gt; Performer
}


2. Add a class extension on Orchestra to conform to the Performers protocol:

extension Orchestra: Performers {
    var numberOfSections: Int {
        return 2
    }

    func numberOfPerformers(inSection section: Int) -&gt; Int {
        if section == 0 {
            return performers.count ?? 0
        } else {
            return nonPerformers.count ?? 0
        }
    }

    func performer(atIndex index: Int, inSection section: Int) -&gt; Performer {
        if section == 0 {
            return performers[index]
        } else {
            return nonPerformers[index]
        }
    }
}


3. Modify the data source to use the protocol

class OrchestraViewDataSource: NSObject, UITableViewDataSource {

    var performers: Performers?

    override init(performers: Performers?) {
        super.init()
        self.performers = performers
    }

    func numberOfSections(in tableView: UITableView) -&gt; Int {
        return performers?.numberOfSections ?? 0
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
        return performers?.numberOfPerformers(inSection: section) ?? 0
    }

    //... Additional code omitted
}


4. Pass the orchestra instance to the data source

let currentOrchestra = User.shared.currentOrchestra
let dataSource = OrchestraViewDataSource(performers: orchestra)