2016-11-16 57 views
0

的Xcode 8帮忙,提供一个自动生成你的NSManagedObjectextension,它看起来像这样:findOrCreate斯威夫特卡伦特3没有硬编码的entityName

// Animal+CoreDataProperties.swift 

import Foundation 
import CoreData 

extension Animal { 

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Animal> { 
    return NSFetchRequest<Animal>(entityName: "Animal"); 
    } 

    // etc... 
} 

这是伟大的,因为我们不再有硬编码字符串,以创建NSFetchRequest对象。然而,苹果公司并未提供协议来提及这种方法,也不提供entityName本身。

例如,如果我想创建这样的方法:

protocol ManagedObjectType: class {} 

extension ManagedObjectType where Self: NSManagedObject { 

    static func findOrCreate(inContext context: NSManagedObjectContext, matchingPredicate predicate: NSPredicate) -> Self { 
    // etc... 
    } 
} 

...有没有办法,我趁fetchRequest方法的任何NSManagedObject子类(因为它只是定义),所以我不得不再次硬编码这些字符串自己(即使Xcode已经这样做)。

确实有办法解决这个问题吗?我在想沿着这些路线的东西:

protocol ManagedObjectType: class { 
    static func fetchRequest() -> NSFetchRequest<NSFetchRequestResult> 
} 

extension Animal: ManagedObjectType {} 

但是,这并不工作,因为协议不支持where条款,所以我不能指定SelfNSFetchRequestResult,这意味着,当我来用它,像这样:

let request: NSFetchRequest<Self> = self.fetchRequest() 

... Xcode中给了我这个错误:

'fetchRequest' produces 'NSFetchRequest<NSFetchRequestResult>', not the expected contextual result type 'NSFetchRequest<Self>'

有没有人解决了这个了吗?

回答

1

您可以将模板用于此目的。所以你的代码看起来像这样:

static func findOrCreate<T: NSManagedObject>(inContext context: NSManagedObjectContext, matchingPredicate predicate: NSPredicate) -> T { 
    // etc... 
} 
+0

这实际上并不奏效,因为我仍然无法在'T'上调用'fetchRequest'。不过,我的投票是因为你的答案帮助我达成了一个解决方案(见上文)。 – ganzogo

+0

你可以使它扩展NSManagedObject,然后使用像 Animal.findOrCreate(...) 它会完全一样,你已经完成。纠正我,如果我错了 –

+0

你是对的 - 你可以这样做,但它有点误导。 'findOrCreate'仍然会使用泛型来返回适当类型的东西;该方法在“动物”类上被调用的事实是无关紧要的。例如,这可以很好地工作:'让果实:Fruit = Animal.findOrCreate(...)'(尽管“Fruit”和“Animal”根本不相关)。 – ganzogo

1

最后,稍微不同的方法为我工作。

首先,定义一个它使用一个associatedtype - 因为除非类被标记为final(它是不是在汽车的情况下,你不能引用Self为内泛型类型这是需要 - 生成NSManagedObject子类):

protocol ManagedObjectType: NSFetchRequestResult { 

    associatedtype ResultType: NSFetchRequestResult 

    init(context: NSManagedObjectContext) 
    static func fetchRequest() -> NSFetchRequest<ResultType> 

} 

你需要,你需要在你的helper方法访问在这里添加任何NSManagedObject属性和方法。在我的情况下,到目前为止,这只是init(context:)初始值设定项。

这使得稍微令人费解的标记您的NSManagedObject子类为符合:

extension Animal: ManagedObjectType { 
    typealias ResultType = Animal 
} 

现在你可以提供像这样的辅助方法(注意where条款):

static func findOrCreate<T: ManagedObjectType>(inContext context: NSManagedObjectContext, matchingPredicate predicate: NSPredicate, configure: (T) -> Void) -> T where T.ResultType == T { 

    // You are now able to call fetchRequest like this: 
    let request: NSFetchRequest<T> = T.fetchRequest() 

    // etc... 
} 

由于帮手方法不再需要在NSManagedObject本身上定义,你可以把它们放在任何地方。我在帮助者struct内制作了static方法。