aryaxt
aryaxt

Reputation: 77596

Swift initialize Self in a static methods

Having problem getting this to work, inside User.provideInstance I'm unable to initialize Self and return. Any thoughts?

extension NSManagedObject {
    public convenience init(managedObjectContext: NSManagedObjectContext) {
        let entity = NSEntityDescription.entityForName(String(self.dynamicType), inManagedObjectContext: managedObjectContext)!
        self.init(entity: entity, insertIntoManagedObjectContext: managedObjectContext)
    }
}

public protocol Deserializable {
    static func provideInstance(json: [NSObject: AnyObject]) -> Self
}

@objc(User) public class User: NSManagedObject, Deserializable {

    public static func provideInstance(json: [NSObject: AnyObject]) -> Self {
       let context = DIContainer.instance.resolve(CoreDataStack.self).managedObjectContext
       let instance = self.init(managedObjectContext: context)
       return instance
    }
}

Error is on let instance = self.init(managedObjectContext: context):

Constructing an object of class type Self with a metatype value must use a required initializer

Upvotes: 0

Views: 2551

Answers (2)

Sulthan
Sulthan

Reputation: 130082

Why bother with initializers?

extension NSManagedObject {
    class func provide(managedObjectContext managedObjectContext: NSManagedObjectContext) -> Self {
        let entity = NSEntityDescription.entityForName(String(self.dynamicType), inManagedObjectContext: managedObjectContext)!
        return self.init(entity: entity, insertIntoManagedObjectContext: managedObjectContext)
    }
}

public protocol Deserializable {
    static func provideInstance(json: [NSObject: AnyObject]) -> Self
}

@objc(User) public class User: NSManagedObject, Deserializable {

    public static func provideInstance(json: [NSObject: AnyObject]) -> Self {
        let context = ...
        let instance = self.provide(managedObjectContext: context)
        return instance
    }
}

The problem with initializers is that they are not always inherited, unless they are required. And you cannot create a required initializer in an extension.

Upvotes: 1

user4282669
user4282669

Reputation:

As the error said, you need a required initializer to create an object, incase you subclass. Add final before your class to prevent this error.

Try this if you need to subclass:

@objc(User) public class User: NSManagedObject, Deserializable {

private static func pInstance<T>(json: [NSObject: AnyObject]) -> T {
    let context = DIContainer.instance.resolve(CoreDataStack.self).managedObjectContext
    let copy: NSManagedObject = NSManagedObject(managedObjectContext: context)
    let instance = copy as! T
    return instance
}

public static func provideInstance(json: [NSObject: AnyObject]) -> Self {
        return pInstance(json)
    }
}

Basically, create a helper function to create an instance of T based on the base class, NSManagedObject. Then use it the actual provideInstance function with the inferred type Self.

Upvotes: 1

Related Questions