简体   繁体   中英

'self.init' isn't called on all paths before returning from initializer

I'm working with CoreData and JSON parsing with Decodable following this and encountered an error at the end of the initializer saying 'self.init' isn't called on all paths before returning from initializer :

import Foundation
import CoreData

extension CodingUserInfoKey {
    static let managedObjectContext = CodingUserInfoKey(rawValue: "managedObjectContext")!
}

@objc(Task)
public class Task: NSManagedObject, Decodable {
    
    enum CodingKeys: String, CodingKey {
        case diff, title, desc, doc
    }
    
    required convenience public init(from decoder: Decoder) throws {
        guard let context = decoder.userInfo[CodingUserInfoKey.managedObjectContext] as? NSManagedObjectContext else {
            print("Decode context error")
            return
        }
        guard let entity = NSEntityDescription.entity(forEntityName: "Task", in: context) else {
            print("Decode entity error")
            return
        }
        self.init(entity: entity, insertInto: context)
        do {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.diff = try container.decode(String.self, forKey: .diff)
            self.title = try container.decode(String.self, forKey: .title)
            self.desc = try container.decode(String.self, forKey: .desc)
            self.doc = try container.decode(String.self, forKey: .doc)
        } catch {
            print("Decode key error")
        }
    }
    
}

Am I missing something?

As it notes, you haven't called self.init on all paths. For example, if context is nil, then you return without calling self.init .

If you want to exit this initializer without creating an instance, you'll need to throw an error, not just return.

Since this init throws, it also doesn't make sense to catch errors and then discard them. Just let them throw to the caller.

You should probably throw a custom error in guard statements instead of just returning. Also you should remove do-catch from decoder function calls:

enum ManagedObjectError: Error {
    case decodeContextError
    case decodeEntityError
}

required convenience public init(from decoder: Decoder) throws {
    guard let context = decoder.userInfo[CodingUserInfoKey.managedObjectContext] as? NSManagedObjectContext else {
        throw ManagedObjectError.decodeContextError
    }
    guard let entity = NSEntityDescription.entity(forEntityName: "Task", in: context) else {
        throw ManagedObjectError.decodeEntityError
    }
    self.init(entity: entity, insertInto: context)
    
    let container = try decoder.container(keyedBy: CodingKeys.self)
    self.diff = try container.decode(String.self, forKey: .diff)
    self.title = try container.decode(String.self, forKey: .title)
    self.desc = try container.decode(String.self, forKey: .desc)
    self.doc = try container.decode(String.self, forKey: .doc)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM