【问题标题】:Swift - Fetch method with GenericsSwift - 使用泛型获取方法
【发布时间】:2014-06-24 18:32:13
【问题描述】:

想法是使用 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


    【解决方案1】:

    如果正如@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 类方法。

      【讨论】:

      • 如果可以的话,我不会使用绑定到objective-c
      • 感谢大卫的意见。我认为您对 “但是,由于您的模型对象需要将 NSManagedObject 作为超类,因此尝试避免“绑定到 Objective-c”确实毫无意义” 所以这是一个很好的解决方案你向我提出的 Jean 和建议:使用注解 @objc(Users) 和 NSStringFromClass。更清晰。我更喜欢这个而不是扩展名。根据您之前的建议,您关于插入的解决方案与我采用的相同(没有 EntityWithName)。谢谢
      【解决方案3】:

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

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

      向下钻取到实体名称。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-04-17
        • 2016-10-26
        • 1970-01-01
        • 1970-01-01
        • 2022-06-10
        • 2011-05-11
        • 2016-04-15
        相关资源
        最近更新 更多