简体   繁体   English

CoreData和Codable类编译器错误:从初始化程序返回之前,未在所有路径上调用'self.init'

[英]CoreData and Codable class compiler error: 'self.init' isn't called on all paths before returning from initializer

After following instructions from this answer: https://stackoverflow.com/a/46917019/6047611 按照此答案中的说明进行操作后: https : //stackoverflow.com/a/46917019/6047611

I am running into the compiler error 'self.init' isn't called on all paths before returning from initializer. 'self.init' isn't called on all paths before returning from initializer.编译器错误'self.init' isn't called on all paths before returning from initializer. super.init() isn't allowed. 不允许使用super.init() However, calling self.init(entity: entity, insertInto: context) and then initializing all of the properties in the class somehow doesn't fully initialize the class. 但是,调用self.init(entity: entity, insertInto: context) ,然后初始化该类中的所有属性不能完全初始化该类。

I'm lost. 我迷路了。 I'm pretty new to CoreData and am not comfortable with it yet, so I'm hoping this is an issue of my own ignorance. 我对CoreData刚起步,还不太满意,所以我希望这是我自己的无知问题。 Any ideas on how to fix this error? 关于如何解决此错误的任何想法?

import Foundation
import CoreData

class Product: NSManagedObject, Encodable, Decodable
{
    @NSManaged var mongoID:[String:String]
    @NSManaged var title:String
    @NSManaged var productID:Int
    @NSManaged var mpn:String
    @NSManaged var listPrice:Float
    @NSManaged var price:Float
    @NSManaged var uom:String
    @NSManaged var uomQty:Int
    @NSManaged var inventory:Float
    @NSManaged var minSaleQty:Int
    @NSManaged var desc:String

    @NSManaged var categories:[String]
    @NSManaged var imageURL:String
    @NSManaged var upc:String
    @NSManaged var quantity:Int
    @NSManaged var disc:Bool

    enum CodingKeys: String, CodingKey {
        case mongoID = "mongoID"
        case title = "title"
        case productID = "productID"
        case mpn = "mpn"
        case listPrice = "listPrice"
        case price = "price"
        case uom = "uom"
        case uomQty = "uomQty"
        case inventory = "inventory"
        case minSaleQty = "minSaleQty"
        case desc = "desc"
        case categories = "categories"
        case imageURL = "imageURL"
        case upc = "upc"
        case quantity = "quantity"
        case disc = "disc"
    }

    required convenience init(from decoder:Decoder) throws
    {
        guard let context = decoder.userInfo[CodingUserInfoKey.context!] as? NSManagedObjectContext else { print("failed context get"); return }
        guard let entity = NSEntityDescription.entity(forEntityName: "Product", in: context) else { print("failed entity init"); return }


        self.init(entity: entity, insertInto: context)

        let container = try decoder.container(keyedBy: CodingKeys.self)

        self.mongoID = try container.decodeIfPresent([String:String].self, forKey: .mongoID) ?? ["$id":"nil"]
        self.title = try container.decodeIfPresent(String.self, forKey: .title) ?? ""
        self.productID = try container.decodeIfPresent(Int.self, forKey: .productID) ?? 0
        self.mpn = try container.decodeIfPresent(String.self, forKey: .mpn) ?? ""
        self.listPrice = try container.decodeIfPresent(Float.self, forKey: .listPrice) ?? 0.0
        self.price = try container.decodeIfPresent(Float.self, forKey: .price) ?? 0.0
        self.uom = try container.decodeIfPresent(String.self, forKey: .uom) ?? ""
        self.uomQty = try container.decodeIfPresent(Int.self, forKey: .uomQty) ?? 0
        self.inventory = try container.decodeIfPresent(Float.self, forKey: .inventory) ?? 0.0
        self.minSaleQty = try container.decodeIfPresent(Int.self, forKey: .minSaleQty) ?? 0
        self.desc = try container.decodeIfPresent(String.self, forKey: .desc) ?? ""

        self.categories = try container.decodeIfPresent([String].self, forKey: .categories) ?? [""]
        self.imageURL = try container.decodeIfPresent(String.self, forKey: .imageURL) ?? ""
        self.upc = try container.decodeIfPresent(String.self, forKey: .upc) ?? ""
        self.quantity = try container.decodeIfPresent(Int.self, forKey: .quantity) ?? 0
        self.disc = try container.decodeIfPresent(Bool.self, forKey: .disc) ?? false
    }//'self.init' isn't called on all paths before returning from initializer

    public func encode(to encoder: Encoder) throws
    {

    }
}


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

This compiler error is not related to Core Data. 此编译器错误与核心数据无关。 It is caused by the two guard statements which can return before self.init is called. 它是由两个可以在self.init之前return guard语句引起的。

In the statement below, if context is nil, the else condition will print "failed context get" and then return : 在下面的语句中,如果context为nil,则else条件将显示“失败的上下文get”,然后return

guard let context = decoder.userInfo[CodingUserInfoKey.context!] as? NSManagedObjectContext 
else { print("failed context get"); return }

You are attempting to return before self.init has been called. 您试图在self.init之前返回。 This is not allowed. 这是不允许的。 Your convenience initializer must return a properly initialized object. 您的便利初始化程序必须返回正确初始化的对象。

However, you have a way out in case either guard statement cannot be satisfied: you can throw an exception. 但是,您有一条出路以防任何一个guard声明都无法满足:您可以throw异常。 It then becomes the responsibility of the caller to handle the exception in whatever way makes sense. 然后,调用者有责任以任何合理的方式处理异常。

To do this, you would need to create an enum that conforms to the Error protocol, for example: 为此,您需要创建一个符合Error协议的enum ,例如:

enum ProductError: Error {
    case contextMissing
    case entityCreationFailed
}

You could then rewrite the guard statements like this: 然后,您可以像下面这样重写guard语句:

guard let context = decoder.userInfo[CodingUserInfoKey.context!] as? NSManagedObjectContext 
else { print("failed context get"); throw ProductError.contextMissing }

When creating Product you can do this: 创建Product您可以执行以下操作:

let product = try? Product(from: decoder)  
//product is an optional, might be nil

Or this: 或这个:

if let product = try? Product(from: decoder) {
    //product is not an optional, cannot be nil
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在从初始化程序返回之前,不会在所有路径上调用“self.init” - 'self.init' isn't called on all paths before returning from initializer json.swift 错误是 Self.init 未在委托初始化程序的所有路径上调用 - json.swift error is Self.init isn't called on all paths in delegating initializer 在从初始化程序错误返回之前,不会在所有路径上调用Super.init - Super.init isn't called on all paths before returning from initializer Error 从初始化程序返回之前,并非在所有路径上都调用“ super.init” - 'super.init' isn't called on all paths before returning from initializer Swift:在从初始化程序返回之前没有在所有路径上调用“super.init”? - Swift: 'super.init' isn't called on all paths before returning from initializer? 在从初始化程序返回之前,不会在所有路径上调用“super.init”。 但是没用 - 'super.init' isn't called on all paths before returning from initializer. But it's useless 在从初始化程序返回之前,不会在所有路径上调用super init - super init isn't called on all paths before returning from initializer 解决“从初始化快速返回之前未在所有路径上调用Super.init的问题”。 - Problems getting around 'Super.init isn't called on all paths before returning from initializer swift.' NSViewController的子类:在self.init被称为Error之前委托初始化程序使用'self' - Subclass of NSViewController: use of 'self' in delegating initializer before self.init is called Error 在自定义UIGestureRecognizer类中调用self.init之前使用的self - Self used before self.init called in custom UIGestureRecognizer class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM