Saya memiliki satu kelas pengontrol tampilan yang saya gunakan kembali di beberapa layar, pada layar yang berbeda saya ingin menyediakan sumber data yang berbeda. VC saya terlihat seperti ini:

class SpotViewController: UIViewController {

    var dataSource: SpotDataSource!
}

Sekarang saya ingin memiliki dua Kelas Sumber Data yang berbeda

class PersonalSpotDataSource {}
class ExploreSpotDataSource {}

Sekarang saya ingin membuat semacam protokol bersama yang membuat dua kelas di atas mengimplementasikan properti berikut:

var spots: [Spot]
var title: String

Dan kemudian saya ingin agar konstruksi bersama itu sesuai dengan UITableViewDataSource karena ia memiliki semua yang dibutuhkannya yang hanya daftar tempat dan judul. Dan kemudian kembali ke kelas pertama saya, saya dapat menyediakan salah satu kelas (Pribadi atau jelajahi) sebagai sumber data VC saya.

Apakah ini mungkin?

2
LoganHenderson 1 Januari 2018, 03:01

1 menjawab

Jawaban Terbaik

Jadi, pertama-tama tentukan protokol Anda:

protocol SpotDataSource {
    var spots: [Spot] { get }
    var title: String { get }
}

Kemudian tentukan dua kelas Anda agar sesuai dengan protokol itu:

class PersonalSpotDataSource: SpotDataSource {
    let spots = [Spot(name: "foo"), Spot(name: "bar")]
    let title = "Foobar"
}

class ExploreSpotDataSource: SpotDataSource {
    let spots = [Spot(name: "baz"), Spot(name: "qux")]
    let title = "Bazqux"
}

Jelas, implementasi Anda dari ini akan lebih canggih daripada yang di atas, tetapi ini menggambarkan ide dasarnya.

Bagaimanapun, setelah melakukan itu, tentukan UITableViewDataSource yang menggunakan protokol ini:

class SpotTableViewDataSource: NSObject {
    let spotDataSource: SpotDataSource

    init(spotDataSource: SpotDataSource) {
        self.spotDataSource = spotDataSource
        super.init()
    }
}

extension SpotTableViewDataSource: UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return spotDataSource.spots.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "SpotCell", for: indexPath) as! SpotCell
        cell.spotLabel.text = spotDataSource.spots[indexPath.row].name
        return cell
    }
}

Terakhir, tentukan pengontrol tampilan tabel Anda untuk menggunakan UITableViewDataSource ini, meneruskannya SpotDataSource apa pun yang Anda inginkan:

class PersonalSpotTableViewController: UITableViewController {

    private let dataSource = SpotTableViewDataSource(spotDataSource: PersonalSpotDataSource())

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.dataSource = dataSource
    }

}

Catatan, di kelas pengontrol tampilan tabel itu, saya mendefinisikan sumber data sebagai properti yang disimpan karena pengontrol tampilan tabel tidak menyimpan referensi yang kuat ke sumber data dan/atau delegasi mereka, tetapi kami ingin itu tetap ada.

Jelas, akan lebih anggun jika kita bisa meletakkan metode UITableViewDataSource di dalam implementasi default protokol SpotDataSource, tapi sayangnya kita tidak bisa. Jadi, Anda harus membuat objek konkret yang sesuai dengan UITableViewDataSource dan menggunakan protokol SpotDataSource Anda, seperti diuraikan di atas.

2
Rob 1 Januari 2018, 00:33