2016-11-16 30 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方法。