Я создаю приложение для устройств iOS и пытаюсь использовать соответствия протокола, чтобы сделать код более гибким.
В частности, я создал протокол DatabaseService
, который предоставляет методы для запросаобщая база данных.
Ранее, используя Firebase Firestore, я знал, что некоторые методы возвращают элемент ListenerRegistration
, который может быть remove()
'd.
В моей попытке сделать это поведение общим, я создал протокол Disposable
и установил его как тип возврата некоторых DatabaseService
методов.
При создании реализации FirestoreDatabaseService
, котораясоответствует DatabaseService
, однако я заметил, что ListenerRegistration
- это протокол, а не класс.
Поэтому я решил попытаться согласовать ListenerRegistration
с Disposable
с этим расширением:
extension Disposable where Self: ListenerRegistration {
// The Disposable protocol has only this function,
// that disposes the listener on deinit.
func dispose() {
// This makes the Disposable dispose on the Registration's remove()
self.remove()
}
}
Поэтому мои FirestoreDatabaseService
методы возвращают ListenerRegistration
s, которые, как я предполагал, будут совместимыс Disposable
.Компилятор, однако, предлагает мне принудительно привести результат as! Disposable
, что кажется неправильным.
Чего мне не хватает?Я уверен, что должен быть лучший способ.
Большое спасибо.
РЕДАКТИРОВАТЬ: Чтобы уточнить мою фактическую потребность:
Я хочу иметьуниверсальный протокол DatabaseService
, который можно использовать в качестве образца для любой реальной службы, связанной с базой данных, которую я мог бы добавить.(Firebase, AWS, Azure и т. Д.)
Например, функция fetchDeck(id: String, completion: @escaping (Deck) -> Void) -> Disposable
может быть реализована в FirestoreDatabaseService
как
fetchDeck(id: String, completion: @escaping (Deck) -> Void) -> Disposable {
return Firestore.firestore().document("decks/\(id)").addSnapshotListener { snapshot, error in
// Here goes the actual code
}
}
Проблема в том, что эта функция вернет ListenerRegistration
в то время как для соответствия моего протокола требуется Disposable
.
Как я могу соединить ListenerRegistration
с Disposable
, при этом оба протокола являются протоколами?Я не хочу использовать ListenerRegistration
в качестве возвращаемого типа, потому что он не будет независимым от бэкэнда.
Если говорить точнее, мой протокол Disposable
требует реализации функции dispose()
, чтотакое поведение выражается как ListenerRegistration
remove()
РЕДАКТИРОВАТЬ: Решение этой конкретной проблемы
Я нашел решение, которое может помочь любомув той же ситуации.Это может не относиться к вам, если вам нужен другой тип соответствия.
Вместо того, чтобы пытаться вернуть сам ListenerRegistration
, я создал AnonymousDisposable
после чертежа RxSwift.
The AnonymousDisposable
соответствует Disposable
и принимает замыкание в качестве параметра, который является кодом для вызова dispose()
.Теперь я могу вернуть экземпляр AnonymousDisposable
и вызвать его dispose()
при необходимости.
Вы можете прочитать подробнее здесь .