【发布时间】:2018-01-04 19:22:11
【问题描述】:
用例
我的 Firebase 中的大多数数据项(例如:RecipeItem、User)都有一个超类 (FirebaseObject) 和子类。我在超类中创建了一个自动更新子类中数据的函数,现在我正在尝试创建一个带有闭包的函数,该闭包在对象更新时被调用。
代码
class FirebaseObject {
private var closures: [((FirebaseObject) -> Void)] = []
public func didChange(completion: @escaping (((FirebaseObject) -> Void))) {
// Save closures for future updates to object
closures.append(completion)
// Activate closure with the current object
completion(self)
}
//...
}
这会使用初始对象调用闭包并将其保存以供以后更新。在我的 Firebase 观察者中,我现在可以在数据更新后通过调用激活所有闭包:
self.closures.forEach { $0(self) }
要添加这些侦听对象更改的闭包,我需要这样做:
let recipeObject = RecipeItem(data)
recipeObject.didChange { newFirebaseObject in
// Need to set Type even though recipeObject was already RecipeItem
// this will never fail
if let newRecipeObject = newFirebaseObject as? RecipeItem {
// Do something with newRecipeObject
}
}
问题
有没有办法让完成处理程序返回子类的类型,这样我就不必执行as? Subclass,即使它永远不会失败?我尝试使用泛型类型来执行此操作,但我无法弄清楚,我不确定这是否是正确的解决方案。
我想将大部分代码保留在 FirebaseObject 类中,因此在创建新子类时不需要添加大量代码。
编辑
基于this article我尝试在创建子类时添加类型:
class RecipeItem: FirebaseObject<RecipeItem> {
//...
}
class FirebaseObject<ItemType> {
private var handlers: [((ItemType) -> Void)] = []
public func didChange(completion: @escaping (((ItemType) -> Void))) {
//...
这会编译,但是一旦 RecipeItem 初始化它就会崩溃。我也试过了
class RecipeItem: FirebaseObject<RecipeItem.Type> {
//...
}
但是当我尝试访问 didChange 闭包中的 RecipeItem 数据时,这会产生一个有趣的编译器错误:
实例成员“title”不能用于类型“RecipeItem”
【问题讨论】: