2017-08-30 87 views
0

我正在为我的核心数据模型设计数据管理器,并且想创建一个通用函数来获取类的亲属。使用通用函数获取核心数据实体亲属

我已经创建了一个协议,允许为每种数据类型构建管理器。在这个协议中,我已经定义了两个相关的类型T和K以及几个简单的函数。现在我被一个类亲戚抓取方法卡住了 - 我需要指出T有K个亲戚。我妄图创建一些协议,通过相互的属性来表示这种关系,所以这两个类都可以符合这个协议。任何想法,甚至有可能吗?

import Foundation 
import CoreData 

protocol DataManager { 

    associatedtype T: NSManagedObject, NSFetchRequestResult 
    associatedtype K: NSManagedObject, NSFetchRequestResult // Relative 

    static var sharedInstance: Self { get } 

    static func getAll(sorted: [NSSortDescriptor]?, context: NSManagedObjectContext) -> [T]? 
    static func insert(item: T) 
    static func update(item: T) 
    static func clean() 
    static func deleteById(id: String) 

    // Relatives 
    static func getRelatives(by: T) -> [K]? 
    static func get(byRelative: K) -> [T]? 
} 

extension DataManager { 

    static func getAll(sorted: [NSSortDescriptor]?, context: NSManagedObjectContext) -> [T]? { 

     guard let fetchRequest: NSFetchRequest<T> = T.fetchRequest() as? NSFetchRequest<T> else { return nil } 
     fetchRequest.sortDescriptors = sorted 

     var results: [T]? = nil 

     do { 
      results = try context.fetch(fetchRequest) 
     } catch { 
      assert(false, error.localizedDescription) 
     } //TODO: Handle Errors 

     return results 
    } 
} 


protocol Identifiable { 
    typealias Identity = String 
    var id: Identity? { get } 
} 


extension DataManager where Self.T: Identifiable { 

    static func get(by id: T.Identity, context: NSManagedObjectContext) -> T? { 

     guard let fetchRequest: NSFetchRequest<T> = T.fetchRequest() as? NSFetchRequest<T> else { return nil } 

     fetchRequest.predicate = NSPredicate(format: "%K == %@", "id", id) 

     var rawResults: [T]? = nil 

     do { 
      rawResults = try context.fetch(fetchRequest) 
     } catch { 
      assert(false, error.localizedDescription) 
     } //TODO: Handle Errors 


     if let result = rawResults?.first { 
      return result } 
     else { return nil } 
    } 
} 

回答

0

那么,我已经创建了一个解决方案。 我们可以找出所有关系与特定的类:

let relationships = T.entity().relationships(forDestination: K.entity()) 

它使我们能够找到一个项目的所有ID为每个关系(我们可以有相同的相对实体一对多的关系):

let relativesIDs = item.objectIDs(forRelationshipNamed: relationship.name) 

因此,我们可以使用这些ID从另一个类中获取记录。

static func getRelatives(of item: T, context:NSManagedObjectContext) -> [K]? { 

    guard let fetchRequest: NSFetchRequest<K> = K.fetchRequest() as? NSFetchRequest<K> else { return nil } 
    fetchRequest.fetchBatchSize = 100 

    var results: [K]? = nil 

    var resultSet: Set<K> = [] // doesn't allow duplicates 

    let relationships = T.entity().relationships(forDestination: K.entity()) 

    for relationship in relationships { 

     let relativesIDs = item.objectIDs(forRelationshipNamed: relationship.name) 
     let predicate = NSPredicate(format: "self IN %@", relativesIDs) 
     fetchRequest.predicate = predicate 

     var batchResults: [K] = [] 

     do { 
      batchResults = try context.fetch(fetchRequest) 
     } catch { 
      assert(false, error.localizedDescription) 
     } //TODO: Handle Errors 

     if batchResults.count > 0 { resultSet = resultSet.union(Set(batchResults)) } 
    } 

    if resultSet.count > 0 { results = Array(resultSet) } 

    return results 
} 

我不知道,这是最完美的解决方案,但它工作:-)