Reputation: 4023
I have a generic protocol I'm using to parse the fetched data:
protocol DataParseDelegate: AnyObject {
associatedtype FetchResult
func didFetchData(data: FetchResult?, error: Error?)
}
extension DataParseDelegate {
func didFetchData(data: FetchResult?, error: Error?) {
// process data
}
}
which is within a view controller that resolves to a certain type:
class ParentViewController<T>: UIViewController {}
class ChildViewController: ParentViewController<DataModel>, DataParseDelegate {
typealias FetchResult = DataModel
override func viewDidLoad() {
super.viewDidLoad()
FirebaseService.delegate = self
FirebaseService.shared.db.downloadData()
}
func didFetchData(data: DataModel?, error: Error?) {
// process data
}
}
I'm using a delegate to pass the fetched data to the view controller:
class FirebaseService {
static let shared = FirebaseService()
var db: Firestore! {
let settings = FirestoreSettings()
Firestore.firestore().settings = settings
let db = Firestore.firestore()
return db
}
weak var delegate: DataParseDelegate?
func downloadData() {
let first = db?.collection("myData")
.order(by: "date")
.limit(to: 8)
first?.getDocuments(completion: { [weak self] (snapshot: QuerySnapshot?, error: Error?) in
// handle errors
self?.delegate?.didFetchData(data: nil, error: error)
// parse the snapshot into DataModel
self?.delegate?.didFetchData(data: dataModel, error: nil)
}
}
}
I'm getting the following error:
Protocol 'DataParseDelegate' can only be used as a generic constraint because it has Self or associate type requirements pointing to the delegate:
weak var delegate: DataParseDelegate?
I tried using the following instead of associatedtype
:
protocol DataParseDelegate: AnyObject {
func didFetchData<T>(data: [T]?, error: Error?)
}
extension DataParseDelegate {
func didFetchData<T>(data: [T]?, error: Error?) {
// process data
}
}
But, I get an error that says:
Generic parameter 'T' cannot be inferred
in regards to the delegate:
first?.getDocuments(completion: { [weak self] (snapshot: QuerySnapshot?, error: Error?) in
self?.delegate?.didFetchData(data: nil, error: error) <-----
}
Upvotes: 0
Views: 122
Reputation: 746
For protocols that have associated types, the compiler needs to know exactly what type the conforming object is. To make that happen, we can either use a conforming concrete type directly or use the protocol as a generic constraint. The actual types that are being referred to won’t be known unless we provide some additional context. So you can give the FirebaseService a concrete type:
weak var delegate: ChildViewController?
That will work but maybe this is not what you want. Please read this excellent article by John Sundell: Why can’t certain protocols, like Equatable and Hashable, be referenced directly?
Upvotes: 1