Swift - 使用泛型的Fetch方法

时间:2014-06-24 18:32:14

标签: generics core-data swift

Idea是使用Coredata获取“Typed”数据。

更新

class func retrieve<T: AnyObject>(entityName:T.Type, sortBy:String? = nil, isAscending:Bool? = true, predicate:NSPredicate? = nil) -> AnyObject[]    {

    println("\(entityName)")
    let request = NSFetchRequest(entityName: "Users")
    request.returnsObjectsAsFaults = false
    if predicate != nil {
        request.predicate = predicate
    }

    if (sortBy != nil){
        var sorter: NSSortDescriptor = NSSortDescriptor(key: sortBy , ascending: isAscending!)
        request.sortDescriptors = [sorter]
    }


    var error: NSError? = nil
    var fetchedResult = myDataModel.managedObjectContext.executeFetchRequest(request, error: &error)
    if !error {
        println("errore: \(error)")
    }


    println("retrieved \(fetchedResult.count) elements for \(entityName)")
    return fetchedResult

}

现在,我上面写的内容在语法上是正确的,但我相信还有另一种方法可以做同样的事情,也许更“轻松”。我认为建议很明确:) 我试图从 entityName 输入参数

获取类名

以下面的方式或类似的方式调用此函数:

 var xx = myDataModel.retrieve(Users.self)

,其中

 Users: NSManagedeObject
你有什么建议吗?

3 个答案:

答案 0 :(得分:2)

只要您使用NSStringFromClass

确保模型类具有非错位名称,就可以使用@objc(ModelClassName)
let request = NSFetchRequest(entityName:NSStringFromClass(entityClass))

另一种选择,更适合你的选择可能是:

protocol EntityWithName {
    class func entityName() -> String
}

extension MyModelObject : EntityWithName {
    class func entityName() -> String {
        return "MyModelObject"
    }
}

extension NSManagedObjectContext {

    // Create an instance of T and insert it into the Context (this is normal)
    func insert<T:NSManagedObject where T:EntityWithName>(entityClass:T.Type) -> T? {
        let entityDescription = NSEntityDescription.entityForName(entityClass.entityName(), inManagedObjectContext: self)

        if !entityDescription {
            return nil
        }

        return NSManagedObject(entity: entityDescription, insertIntoManagedObjectContext: self) as? T
    }
}

let myModelObject = myContext.insert(MyModelObject.Self)

但是,由于您的模型对象需要NSManagedObject作为超类,因此尝试避免“绑定到objective-c”实际上是毫无意义的。

另外一个观察,如果你使用mogenerator和它的新的快速生成选项,那么EntityWithName方法变得更容易,你可以添加:

extension MyModelObject : EntityWithName {}

对于每个用户可修改的类文件(不是_ one),它应该没问题,因为mogenerator生成了一个entityName类方法。

答案 1 :(得分:2)

如果@David指出,你将@objc(ModelClassName)添加到Model类中,这里是一个简化版本:

func retrieve<T: NSManagedObject>(entityClass:T.Type, sortBy:String? = nil, isAscending:Bool = true, predicate:NSPredicate? = nil) -> T[] {
    let entityName = NSStringFromClass(entityClass)
    let request    = NSFetchRequest(entityName: entityName)

    request.returnsObjectsAsFaults = false
    request.predicate = predicate

    if (sortBy != nil) {
        var sorter = NSSortDescriptor(key:sortBy , ascending:isAscending)
        request.sortDescriptors = [sorter]
    }

    var error: NSError? = nil
    var fetchedResult = myDataModel.managedObjectContext.executeFetchRequest(request, error: &error)
    if !error {
        println("errore: \(error)")
    }

    println("retrieved \(fetchedResult.count) elements for \(entityName)")
    return fetchedResult
}

可以这样使用它:

@objc(Client)
class Client : NSManagedObject {
    ...    
}

retrieve(Client)  // This would get all clients in the database.

答案 2 :(得分:0)

我似乎无法让@objc注释为我工作,所以我使用了:

let fetchRequest = NSFetchRequest(entityName: NSStringFromClass(entityClass).componentsSeparatedByString(".").last!)

深入到实体名称。