[英]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.