Must call a designated initializer of the superclass 'Day' error

别说谁变了你拦得住时间么 提交于 2019-12-08 10:56:05

问题


In my app i tried to make saving data with data persistence but i get this error: Must call a designated initializer of the superclass 'Day' error.

Here is my code:

class Day: NSObject, NSCoding { // NEMA NSCODING I NSOBJECT
var dayName: String
var subjects: [Subject]?

init(dayName: String) {
    self.dayName = dayName
}

struct PropertyKey {
    static var dayName = "dayName"
    static var subjects = "subjects"
}

func encode(with aCoder: NSCoder) {
    aCoder.encode(dayName, forKey: PropertyKey.dayName)
    aCoder.encode(subjects, forKey: PropertyKey.subjects)
}

// Archiving paths
static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
static let ArchiveURL = DocumentsDirectory.appendingPathComponent("workingDays")//-namesto meals

required convenience init?(coder aDecoder: NSCoder) {
    guard let dayName = aDecoder.decodeObject(forKey: PropertyKey.dayName) as? String else {
        os_log("Unable to decode the dayName for a Day object.", log: OSLog.default, type: .debug)
        return nil
    }
    let subjects = aDecoder.decodeObject(forKey: PropertyKey.subjects) as? [Subject]
    self.init(dayName: dayName)
}

}

And here is the other class:

class Subject: Day {
var subjectName: String
var startsAt: String?
init(dayName: String,subjectName: String) {
    self.subjectName = subjectName
    super.init(dayName: dayName)
}
required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder) // here I get the error
}

}

Am I going to save the data this way with implementing data persistence only in Day class and why do I get that error? I am a beginner and I'm doing it based on this apple documentation -

https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=12&cad=rja&uact=8&ved=0ahUKEwjWoIHk4uvXAhUHaFAKHbQFCHcQFghbMAs&url=https%3A%2F%2Fdeveloper.apple.com%2Flibrary%2Fcontent%2Freferencelibrary%2FGettingStarted%2FDevelopiOSAppsSwift%2FPersistData.html&usg=AOvVaw24H5Uo4RyRY7NYIlztlgCj

Any help would be much appreciated.


回答1:


The problem is caused by calling self.init in init?(coder of Day. That call makes the initializer convenient and the subclass is not able to fulfill the requirements to call a designated initializer.

The solution is to initialize the properties directly

required init?(coder aDecoder: NSCoder) {
    self.dayName = aDecoder.decodeObject(forKey: PropertyKey.dayName) as! String
    self.subjects = aDecoder.decodeObject(forKey: PropertyKey.subjects) as? [Subject]
}

By the way: You are encoding always dayName as a non-optional string so it never can be nil when being decoded. The guard is useless.

In the subclass you might need to add code to en-/decode the properties of the subclass and call super to consider also the properties of the superclass.

class Subject: Day {
    var subjectName: String
    var startsAt: String?

    init(dayName: String, subjectName: String) {
        self.subjectName = subjectName
        super.init(dayName: dayName)
    }

    override func encode(with aCoder: NSCoder) {
        super.encode(with: aCoder)
        aCoder.encode(subjectName, forKey: "subjectName")
        aCoder.encode(startsAt, forKey: "startsAt")
    }

    required init?(coder aDecoder: NSCoder) {
        subjectName = aDecoder.decodeObject(forKey: "subjectName") as! String
        startsAt = aDecoder.decodeObject(forKey: "startsAt") as? String
        super.init(coder: aDecoder)
    }
}

The question for the sense of using a subclass as property in its superclass is another story 😉




回答2:


By definition of Required Initializers-:

Write the required modifier before the definition of a class initializer to indicate that every subclass of the class must implement that initializer:

You do not write the override modifier when overriding a required designated initializer:

In your case you made convenience initialiser of superclass required, so subclass have to implement it now -:

Code Correction-:

class Subject: Day {
    var subjectName: String
    var startsAt: String?
    init(dayName: String,subjectName: String) {
        self.subjectName = subjectName
        super.init(dayName: dayName)
    }

    required convenience init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


}


来源:https://stackoverflow.com/questions/47610151/must-call-a-designated-initializer-of-the-superclass-day-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!