【问题标题】:'self.init' isn't called on all paths before returning from initializer在从初始化程序返回之前,不会在所有路径上调用“self.init”
【发布时间】:2020-12-17 13:03:26
【问题描述】:

我正在使用 CoreData 和 JSON 解析,并在 this 之后使用 Decodable 并在初始化程序末尾遇到错误 '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")
        }
    }
    
}

我错过了什么吗?

【问题讨论】:

  • 如果你的任何一个守卫失败了,你将从方法返回而不调用 self.init。这些是它所指的“路径”

标签: ios json swift core-data decodable


【解决方案1】:

您可能应该在guard 语句中抛出自定义错误,而不是仅仅返回。您还应该从解码器函数调用中删除do-catch

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)
}

【讨论】:

    【解决方案2】:

    正如它所指出的,您并没有在所有路径上调用self.init。例如,如果 context 为 nil,则您无需调用 self.init 即可返回。

    如果您想在不创建实例的情况下退出此初始化程序,则需要抛出错误,而不仅仅是返回。

    由于这个init 抛出,捕获错误然后丢弃它们也没有任何意义。让他们扔给调用者。

    【讨论】:

    • 你比我快半分钟 :)
    • @gcharita 您提供了实际代码,而不仅仅是描述它。这是更有用的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    • 2015-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多