我声明了一个带有泛型函数的协议,但似乎在实现后类型推断无法正常工作。
protocol SearchableRealmModel {
static func search<Self: Object>(needle: String) -> Results<Self>?
}
class Thing: Object, SearchableRealmModel {
class func search<Thing>(needle: String) -> Results<Thing>? {
return realm()?.objects(Thing).filter("name == '\(needle)'")
}
}
let things = Thing.search("hello") // works but inferred type is Results<Object>?
此处的问题是things
的推断类型为Results<Object>?
。我意识到可以使用这些变化,
let things: Results<Thing>? = Thing.search("hello")
let things = Thing.search("hello") as Results<Thing>?
但每次必须指定类型是非常重复的。
在我的测试中,使用除Results<..>?
之外的其他类型保持类型推断不变。这可能是因为必须在Self: Object
中指定父类(由于Results
而需要)。
感谢任何帮助。
答案 0 :(得分:1)
这是Swift的仿制机器的限制。编译器可以生成static func search(needle: String) -> Results<Object>?
的具体签名,该签名满足类型约束,因为Object
子类将与此匹配。您可能会向bugs.swift.org提交错误,因为我认为Swift核心团队也会认为这是一个错误,如果不是非常意外的行为。
但是,您可以修改代码以使用协议扩展来执行您想要的操作:
protocol SearchableRealmModel {}
extension SearchableRealmModel where Self: Object {
static func search(needle: String) -> Results<Self> {
return try! Realm().objects(Self).filter("name == '\(needle)'")
}
}
class Thing: Object, SearchableRealmModel {
dynamic var name = ""
}
let result = Thing.search("thing1") // => inferred as Results<Thing>
print(result.first?.name)
如果你想为其他Realm模型自定义实现search
,你可以重新实现那里的函数,编译器将优先考虑协议扩展版本:
class OtherThing: Object, SearchableRealmModel {
dynamic var id = ""
static func search(needle: String) -> Results<OtherThing> {
return try! Realm().objects(OtherThing).filter("id == '\(needle)'")
}
}