【问题标题】:How do I fix "Extra argument in call" when decoding with required convenience init?(coder:)?使用所需的便利初始化解码时如何修复“调用中的额外参数”?(编码器:)?
【发布时间】:2019-10-14 00:28:40
【问题描述】:

我对应用程序开发相对较新,我正在尝试将持久性添加到使用 SwiftUI 编写的家庭作业管理应用程序中。我在我的“UserData”类中实现 NSCoding,并且能够毫无问题地创建编码函数,但是在我设置解码函数后,我在 self.init( ) 线。我的代码到底有什么问题?

class UserData: NSObject, NSCoding, ObservableObject {

    // MARK:- Properties

    @Published var assignments: [Assignment]
    @Published var courses: [Course] = []

    @Published var username: String = ""
    @Published var appState: AppState = AppState(willPresentSplashScreen: false)

...

 // MARK:- NSCoding

    func encode(with coder: NSCoder) {
        coder.encode(assignments, forKey: PropertyKey.assignments)
        coder.encode(courses, forKey: PropertyKey.courses)
        coder.encode(username, forKey: PropertyKey.username)
        coder.encode(appState, forKey: PropertyKey.appState)
    }

    required convenience init?(coder decoder: NSCoder) {

        let assignments = decoder.decodeObject(forKey: PropertyKey.assignments) as? [Assignment]
        let courses = decoder.decodeObject(forKey: PropertyKey.courses) as? [Course]
        let username = decoder.decodeObject(forKey: PropertyKey.username) as? String
        let appState = decoder.decodeObject(forKey: PropertyKey.appState) as? AppState

        self.init(assignments: assignments, courses: courses, username: username, appState: appState)
    }
}

【问题讨论】:

    标签: ios swift nscoding


    【解决方案1】:

    UserData 是一个类,与结构不同,类没有默认的成员初始化器。您需要创建一个接受这些参数的初始化程序。如果没有它,Swift 可以找到的最接近的初始化程序是 init(),它继承自 NSObject - 除了参数名称不匹配,因此会出错。

    您需要创建成员初始化器:

    init(assignments: [Assignment], courses: [Course], username: String, appState: AppState) {
        self.assignments = assignments
        self.courses = courses
        self.username = username
        self.appState = appState
    }
    

    这会给你一个错误,你从init?(coder decoder: NSCoder) 传递的参数需要被解包,因为你有可选项,而初始化程序不需要可选项。

    init?(coder decoder: NSCoder) 是一个失败的初始化器,所以如果一切都不对,你可以返回nil

    required convenience init?(coder decoder: NSCoder) {
    
            guard let assignments = decoder.decodeObject(forKey: PropertyKey.assignments) as? [Assignment],
                let courses = decoder.decodeObject(forKey: PropertyKey.courses) as? [Course],
                let username = decoder.decodeObject(forKey: PropertyKey.username) as? String,
                let appState = decoder.decodeObject(forKey: PropertyKey.appState) as? AppState else {
                    return nil
            }
    
            self.init(assignments: assignments, courses: courses, username: username, appState: appState)
    }
    

    我可能会去掉分配给 coursesusernameappState 的默认值 - 你不需要它们,因为这些值将来自初始化程序

    【讨论】:

    • 非常感谢!那为我修好了。为什么我的参数是可选的,即使我没有明确声明它们?
    • 因为你使用了as? - 有条件的向下转换产生一个可选的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多