泛型方法是否可以根据执行它的类来推断其类型?我使用 CoreData NSManagedObject 模型来存储和检索本地数据,并设法以一种易于阅读和可用的方式使所有内容通用,除了在一个地方。如果用户希望查询本地数据库以获取对象列表,他将编写以下行:
let posts: [Post] = Post.all()
这将正确返回数据库中的“所有”Post 对象,但语法要求定义类型([Post]
)在调用该方法之上Post
类本身(Post.all()
),感觉不必要地多余。有没有什么方法可以简单地通过调用来定义泛型类型all()
方法从Post
班级?我想我可以创建全局函数来获取数据,如下所示:
let posts: [Post] = all()
如果语法如下,则感觉不太可读:
let posts = Post.all()
尝试改进这一点的目的是让任何拿起这个项目的开发人员都可以快速学习其结构和风格,而不需要付出太多的努力。此外,这有望提高未来代码的总体可读性,无论有人正在处理它还是只是出于其他原因阅读它。
为了获得更多见解,以下是有关当前结构的更多信息:
//Model.swift - The model base class. All models extend this class.
class Model: NSManagedObject {
/**
Some other stuff here
**/
//MARK: Fetch
internal class func fetch<T: Model>(predicate: NSPredicate? = nil) -> [T]? {
do {
if let request = NSFetchRequest.FromEntityName(self.entityName) { //Get entity with the name defined in the current class
request.predicate = predicate
if let result = try self.context?.executeFetchRequest(request) as? [T] {
return result
}
}
}
catch let error as NSError {
Log.Error("\(error)")
}
return nil
}
//MARK: Fetch general
class func all<T: Model>() -> [T]? {
if let result: [T] = self.fetch() {
return result
}
Log.warning("No \(self.entityName) found")
return nil
}
}
//Post.swift - An example model class. Extends Model.swift
class Post: Model {
//some fields
}
//Example view controller
class ViewController: UIViewController {
override func viewDidLoad() {
let posts: [Post] = Post.all()
//do stuff
}
}
如果有人对此有任何想法,请告诉我。感谢所有帮助!
在一般情况下,类方法返回“类的类型”(即使对于子类)的典型方法是使用协议扩展和Self
类型。下面是一个示例,它将您的方法简化为最低限度,以使类型检查按照您想要的方式工作:
// define a protocol
protocol ModelType {}
// create a static method on the protocol that returns [Self]
extension ModelType where Self: NSManagedObject {
static func all() -> [Self]? {
return [Self]() // do your fetch here
}
}
// conform to the protocol in your class hierarchy
class Model: NSManagedObject, ModelType {}
class Post: Model {}
let posts = Post.all()
// implicit type of `posts` is `[Post]?`
注意all()
应该由协议扩展提供,但是not协议的要求。如果你声明all()
inside protocol ModelType
,那么你不能让它使用动态分派,如果要使用动态类型,这是必需的。
另请注意,在 Swift 3(以及 macOS 10.12 / iOS 10 / tvOS 10 / watchOS 3)中,Core Data 本身定义了一些 Swift API 快捷方式,这些快捷方式替换了您自己定义的一些快捷方式。注意这个例子来自核心数据的新变化 https://developer.apple.com/library/content/releasenotes/General/WhatNewCoreData2016/ReleaseNotes.html#//apple_ref/doc/uid/TP40017342:
func findAnimals() {
context.performAndWait({
let request = Animal.fetchRequest // implicitly NSFetchRequest<Animal>
do {
let searchResults = try request.execute()
// use searchResults ...
} catch {
print("Error with request: \(error)")
}
})
}
最后,对您选择的风格进行一些评论......
仅供参考,我将所有静态/类方法中的第一个字母大写,就像惯例一样
尝试改进这一点的目的是让任何拿起这个项目的开发人员都可以快速学习其结构和风格,而不需要付出太多的努力。此外,这有望提高未来代码的可读性
我不确定是否会违反语言标准约定(例如中推荐的小写方法名称)Swift 3 API 指南 https://swift.org/documentation/api-design-guidelines)与您的目标非常契合,即让其他刚接触您的代码库的开发人员能够轻松阅读和参与。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)