Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 587
Mark Bridges Avatar asked Nov 27 '16 00:11

Mark Bridges


1 Answers

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)
        }
    }
}
like image 62
Martin R Avatar answered Sep 28 '22 10:09

Martin R