CoreData and Codable class compiler error: 'self.init' isn't called on all paths before returning from initializer
CoreData and Codable class 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.
super.init()
isn't allowed。但是,调用 self.init(entity: entity, insertInto: context)
然后初始化 class 中的所有属性并不能完全初始化 class。
我迷路了。我对 CoreData 还很陌生,还不太适应,所以我希望这是我自己无知的问题。关于如何修复此错误的任何想法?
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")
}
此编译器错误与 Core Data 无关。这是由在调用 self.init
之前可以 return
的两个 guard
语句引起的。
在下面的语句中,如果 context
为 nil,则 else
条件将打印 "failed context get" 然后 return
:
guard let context = decoder.userInfo[CodingUserInfoKey.context!] as? NSManagedObjectContext
else { print("failed context get"); return }
您正试图在调用 self.init
之前 return。这是不允许的。您的便利初始化器必须 return 一个正确初始化的对象。
但是,万一 guard
语句无法满足,您有一个出路:您可以 throw
一个例外。然后调用者有责任以任何有意义的方式处理异常。
为此,您需要创建一个符合 Error
协议的 enum
,例如:
enum ProductError: Error {
case contextMissing
case entityCreationFailed
}
然后您可以像这样重写 guard
语句:
guard let context = decoder.userInfo[CodingUserInfoKey.context!] as? NSManagedObjectContext
else { print("failed context get"); throw ProductError.contextMissing }
创建 Product
时,您可以这样做:
let product = try? Product(from: decoder)
//product is an optional, might be nil
或者这样:
if let product = try? Product(from: decoder) {
//product is not an optional, cannot be nil
}
按照此答案中的说明进行操作后:
我运行进入编译错误'self.init' isn't called on all paths before returning from initializer.
super.init()
isn't allowed。但是,调用 self.init(entity: entity, insertInto: context)
然后初始化 class 中的所有属性并不能完全初始化 class。
我迷路了。我对 CoreData 还很陌生,还不太适应,所以我希望这是我自己无知的问题。关于如何修复此错误的任何想法?
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")
}
此编译器错误与 Core Data 无关。这是由在调用 self.init
之前可以 return
的两个 guard
语句引起的。
在下面的语句中,如果 context
为 nil,则 else
条件将打印 "failed context get" 然后 return
:
guard let context = decoder.userInfo[CodingUserInfoKey.context!] as? NSManagedObjectContext
else { print("failed context get"); return }
您正试图在调用 self.init
之前 return。这是不允许的。您的便利初始化器必须 return 一个正确初始化的对象。
但是,万一 guard
语句无法满足,您有一个出路:您可以 throw
一个例外。然后调用者有责任以任何有意义的方式处理异常。
为此,您需要创建一个符合 Error
协议的 enum
,例如:
enum ProductError: Error {
case contextMissing
case entityCreationFailed
}
然后您可以像这样重写 guard
语句:
guard let context = decoder.userInfo[CodingUserInfoKey.context!] as? NSManagedObjectContext
else { print("failed context get"); throw ProductError.contextMissing }
创建 Product
时,您可以这样做:
let product = try? Product(from: decoder)
//product is an optional, might be nil
或者这样:
if let product = try? Product(from: decoder) {
//product is not an optional, cannot be nil
}