Swift - 使用泛型获取方法

问题描述 投票:0回答:4

想法是使用 Coredata 获取“类型化”数据。

已更新

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

你有什么建议吗?

generics core-data swift
4个回答
3
投票

如果正如@David 指出的那样,您将

@objc(ModelClassName)
添加到您的模型类中,这是一个简化版本:

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
投票

您可以使用

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 {}

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


0
投票

我似乎无法让

@objc
注释为我工作,所以我使用了:

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

深入到实体名称。


0
投票
lazy var persistentContainer: NSPersistentContainer = {
    let persistent = NSPersistentContainer(name: "SuperModelName")
    persistent.loadPersistentStores { _, error in
        print(error?.localizedDescription ?? "")
    }
    return persistent
}()

var moc: NSManagedObjectContext {
    persistentContainer.viewContext
} 

func fetch<T: NSManagedObject>(_ type: T.Type) -> [T] {
    do {
        let fetchRequest = NSFetchRequest<T>(entityName: type.description())
        let fetchItem = try moc.fetch(fetchRequest)
        return fetchItem
    } catch {
        print(error.localizedDescription)
        return []
    }
}

var beverageData: [Beverage] {
    fetch(Beverage.self)
}
© www.soinside.com 2019 - 2024. All rights reserved.