Mark Bridges Mark Bridges - 8 days ago 5
Swift Question

Get class name in convenience init Swift 3

I'm trying to implement my own version of

convenience init(context moc: NSManagedObjectContext)
, the new convenience initialiser on NSManagedObject in iOS 10. Reason being I need to make it compatible with iOS 9.

I've come up with this:

convenience init(managedObjectContext moc: NSManagedObjectContext) {
let name = "\(self)".components(separatedBy: ".").first ?? ""

guard let entityDescription = NSEntityDescription.entity(forEntityName: name, in: moc) else {
fatalError("Unable to create entity description with \(name)")
}

self.init(entity: entityDescription, insertInto: moc)
}


but it doesn't work because of this error...


'self' used before self.init call


Does anyone know how to get around this error, or achieve the same result in another way.

Answer

You can get the type of self with type(of: self) and that works even before self is initialized. String(describing: <type>) returns the unqualified type name as a string (i.e. the type name without the module name), and that is exactly what you need here:

extension NSManagedObject {
    convenience init(managedObjectContext moc: NSManagedObjectContext) {
        let name = String(describing: type(of: self))

        guard let entityDescription = NSEntityDescription.entity(forEntityName: name, in: moc) else {
            fatalError("Unable to create entity description with \(name)")
        }

        self.init(entity: entityDescription, insertInto: moc)
    }
}

You can also add an if #available check to use the new init(context:) initializer on iOS 10/macOS 10.12 or later, and the compatibility code as a fallback on older OS versions:

extension NSManagedObject {
    convenience init(managedObjectContext moc: NSManagedObjectContext) {
        if #available(iOS 10.0, macOS 10.12, *) {
            self.init(context: moc)
        } else {
            let name = String(describing: type(of: self))
            guard let entityDescription = NSEntityDescription.entity(forEntityName: name, in: moc) else {
                fatalError("Unable to create entity description with \(name)")
            }
            self.init(entity: entityDescription, insertInto: moc)
        }
    }
}
Comments