CLLLocationManager dan mengirimkan pembaruan lokasi ke berbagai bagian aplikasi

Di aplikasi saya, saya memiliki layanan latar belakang dan pengontrol tampilan yang memerlukan pembaruan lokasi (tidak terus-menerus). Jadi, menurut saya lebih baik memiliki kelas tunggal untuk menangkap pembaruan lokasi dan mendistribusikannya ke berbagai bagian aplikasi saya daripada mendelegasikannya ke setiap objek yang memerlukan lokasi.

Manajer lokasi saya adalah kelas tunggal yang menyiapkan CLLocationManager, mengaktifkan lokasi ketika ada sesuatu yang memanggil manajer lokasi dan menanyakan lokasi. Cara kerjanya adalah, ia memiliki metode CurrentLocation yang menerima penutupan sebagai argumen. locationManager menyimpan penutupan yang diteruskan ke metode ini dalam sebuah array. Setiap kali metode ini dipanggil, locationManager mengaktifkan pembaruan lokasi dan setelah memiliki lokasi yang cukup baik, ia akan mengeksekusi semua penutupan, meneruskan lokasi yang diperoleh ke dalamnya dan menghapus antrian eksekusi.

Saya mengetahui siklus penyimpanan dan berhati-hati dengan daftar tangkapan yang diberikan di penutupan. Namun, saya mendapatkan thunk for @escaping @callee_guaranteed crash yang langka saat penutupan sedang dijalankan. Terakhir kali saya mendapatkan ini, log mengeluhkan penggunaan yang buruk dari yang lemah. Saya menggunakan objek referensi lemah (self lemah) dalam penutupan, tetapi penutupan lainnya hanya dijalankan jika referensi lemah benar-benar menyimpan referensi ke suatu objek (if let self = self { ... } )

Saya punya beberapa pertanyaan

  1. Apakah ini desain yang buruk? Bisakah saya melakukan ini dengan cara yang lebih baik?

  2. Saya tahu NSNotifications juga merupakan cara yang tepat untuk mengirimkan data ke berbagai bagian aplikasi. Saya ingin tahu apakah ini lebih baik atau lebih buruk dari desain saya dan bagaimana caranya.

  3. Ketika saya ingin mengirimkan pembaruan lokasi terus-menerus ke objek yang berbeda, metode apa yang baik? Seperti, menambahkan pengamat dengan target dan pemilih (ini adalah objektifC-ish)

  4. Saya punya desain lain dalam pikiran. LocationManager saya akan memiliki metode addObserver dengan argumen yaitu objek yang mengimplementasikan protokol untuk menerima pembaruan lokasi. Apakah ini desain yang bagus?


person Brucschothaman Waynekattaraman    schedule 08.07.2020    source sumber
comment
Saya akan merekomendasikan menggunakan Gabungkan Publisher.   -  person Alexander    schedule 08.07.2020
comment
Penerbit adalah desain yang menarik dan saya tidak menyadarinya. Terima kasih. Saya mungkin dapat menggunakannya di proyek saya selanjutnya, tetapi yang ini memerlukan kompatibilitas dengan iOS 12 dan 11.   -  person Brucschothaman Waynekattaraman    schedule 08.07.2020
comment
Anda dapat menggunakan OpenCombine untuk platform lama, ini merupakan implementasi open source dari Combine API. Dan tentu saja ada RxSwift yang sudah ada sejak lama   -  person Alexander    schedule 08.07.2020


Jawaban (1)


Ada solusi yang mirip dengan notifikasi tetapi menurut saya lebih baik, karena Anda dapat memiliki banyak pesan dan lebih mudah untuk menjaga kebersihannya. Jika targetnya adalah iOS 13+, Anda pasti bisa menggunakan Publisher.

Buat protokol untuk singleton Anda

protocol YourLocationManagerDelegate: class {
    func didUpadteUserPosition()
}

Kelas : memungkinkan objek delegasi dapat menjadi referensi yang lemah.

di manajer tunggal Anda buat daftar delegasi

private var delegates: [YourLocationManagerDelegate?] = []

di manajer tunggal Anda, buat metode daftar dan batalkan pendaftaran

func register(Delegate delegate: YourLocationManagerDelegate) {
    if delegates.contains(where: { (delegateToCheck) -> Bool in
        return delegateToCheck === delegate
    }) == false {
        self.delegates.append(delegate)
    }
}

func unregister(Delegate delegate: YourLocationManagerDelegate) {
    self.delegates.removeAll { (delegateToCheck) -> Bool in
        return delegateToCheck === delegate
    }
}

di objek Anda, daftarkan dengan diri yang lemah

weak var this = self
UserLocationManager.shared.register(Delegate: this)

di manajer Anda, ketika Anda mendapatkan pembaruan baru, ulangi delegasi dan panggil pembaruan.

func locationUpdated() {
    for delegate in delegates {
        delegate?.didUpadteUserPosition()
    }
}

karena objek terdaftar sebagai referensi yang lemah, objek tersebut tidak disimpan saat dihilangkan. Selain itu, Anda dapat membatalkan pendaftaran di deinit objek tersebut tetapi itu bukan suatu keharusan.

person Tomo Norbert    schedule 08.07.2020