Using Swift protocols with generics

前端 未结 2 522
独厮守ぢ
独厮守ぢ 2020-12-09 14:34

I have a simple example that seems like it should work:

import CoreData

@objc protocol CoreDataModel {
    @optional class func entityName() -> String
}

         


        
相关标签:
2条回答
  • 2020-12-09 14:52

    From "The Swift Programming Language"

    Because T is a placeholder, Swift does not look for an actual type called T.

    As T is not a real type, it is maybe not useful to cast to T.

    0 讨论(0)
  • 2020-12-09 14:54

    I cannot explain why your code causes a runtime exception. But it works if you change the function prototype

    class func create<T : CoreDataModel>(aClass:T.Type, context:NSManagedObjectContext) -> T 
    

    to

    class func create<T : NSManagedObject where T: CoreDataModel>(aClass:T.Type, context:NSManagedObjectContext) -> T
    

    Assuming that your managed object subclass conforms to the protocol, for example

    extension Event : CoreDataModel {
        class func entityName() -> String {
            return "Event"
        }
    }
    

    then this works and creates a new object:

    let newManagedObject = AbstractModel.create(Event.self, context: context)
    

    Alternatively, you could use the approach from the answer to "Swift: return Array of type self" and define an extension to the NSManagedObjectContext class:

    extension NSManagedObjectContext {
        func create<T : NSManagedObject where T : CoreDataModel >(entity: T.Type) -> T {
            var classname = entity.entityName()
            var object = NSEntityDescription.insertNewObjectForEntityForName(classname, inManagedObjectContext: self) as T
            return object
        }
    }
    

    Then a new object would be created as

    let newManagedObject = context.create(Event.self)
    
    0 讨论(0)
提交回复
热议问题