Чтобы расширить некоторые функциональные возможности моих NSManagedObject
подклассов, я определил ряд протоколов:
protocol ManagedObjectFindable {
static func find(format:String, arguments: [AnyObject]?, inContext context:NSManagedObjectContext, entityName:String?) -> Self?
}
protocol UniquelyIdentifiable: ManagedObjectFindable {
var identifier: NSNumber? { get }
static func findWithIdentifier(identifier: Int, inContext context:NSManagedObjectContext) -> Self?
}
Таким образом, каждый NSManagedObject
, имеющий идентификатор в своей модели данных, может соответствовать UniquelyIdentifiable
.
Для этой цели я использую расширения протокола Swift 2.0, где:
extension UniquelyIdentifiable {
static func findWithIdentifier(identifier: Int, inContext context:NSManagedObjectContext) -> Self? {
return self.find("identifier == %lld", arguments: [NSNumber(longLong: Int64(identifier))], inContext: context, entityName:nil)
}
}
Где найти определяется как:
extension NSManagedObject: ManagedObjectFindable {
/** returns single entity if found, nil otherwise */
class func find(format:String, arguments: [AnyObject]?, inContext context:NSManagedObjectContext, entityName:String? = nil) -> Self? {
let objectEntityName:String
if let name = entityName {
objectEntityName = name
} else {
objectEntityName = String(self)
}
let fetchRequest = NSFetchRequest()
fetchRequest.entity = NSEntityDescription.entityForName(objectEntityName, inManagedObjectContext: context)
fetchRequest.fetchLimit = 1
fetchRequest.predicate = NSPredicate(format: format, argumentArray: arguments)
var persistentEntityº:NSManagedObject?
context.performBlockAndWait {
do {
let fetchResults = try context.executeFetchRequest(fetchRequest)
if (fetchResults.count != 0){
persistentEntityº = fetchResults.first as? NSManagedObject
}
} catch {}
}
if let persistentEntity = persistentEntityº {
return _safeObjectSelfCast(persistentEntity)
} else {
return nil
}
}
}
func _unsafeObjectSelfCast<T>(obj: AnyObject!) -> T { return obj as! T }
func _safeObjectSelfCast<T>(obj: AnyObject) -> T? { return obj as? T }
Теперь эти методы корректно возвращают Self? и компилятор молчит о времени кодирования, однако при компиляции выдает эту ошибку Method 'findWithIdentifier(_:inContext:)' in non-final class must return 'Self' to conform to protocol 'UniquelyIdentifiable'
Теперь дело в том, что если вместо реализации этого метода в расширении протокола я просто расширил бы свой подкласс NSManagedObject
, все будет хорошо, но это убивает цель расширений протокола, когда вы полностью дублируете один и тот же код в десятках ваших NSManagedObject
подклассы.
Любое обходное решение, или я действительно что-то упускаю?