0

What do I need to add to extend the UserModel with AuthenticatedUserModel without getting this error? // 'required' initializer 'init(from:)' must be provided by subclass of 'UserModel'

I know I can also just add the accessToken to the UserModel as optional but I want to understand what's going on so I can understand swift a bit better?

class UserModel: Codable, Identifiable, ObservableObject {
    let id: Int
    let firstName: String?
    let lastName: String?
    let username: String?
    let bio: String?
    let theme: String?
    let imageSrc: String?
    let interests: [String]?
    let followerCount: Int?
    let following: Bool?
    let followingCount: Int?
    let hasCompletedRegistration: Bool?
    let isPrivate: Bool?
    let readerMode: Bool?
    let isActive: Bool?
    let isVerified: Bool?
    let isSuspended: Bool?
    let isAdmin: Bool?
    let isFollowing: Bool?
    let createdAt: String?
    let updatedAt: String?
    
    init(id: Int, firstName: String, lastName: String, bio: String) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName
        
        self.username = ""
        self.bio = ""
        self.theme = ""
        self.imageSrc = ""
        self.interests = [""]
        self.followerCount = 0
        self.following = false
        self.followingCount = 0
        self.hasCompletedRegistration = true
        self.isPrivate = false
        self.readerMode = true
        self.isActive = true
        self.isVerified = false
        self.isSuspended = false
        self.isAdmin = false
        self.isFollowing = false
        self.createdAt = ""
        self.updatedAt = ""
    }
    
    var name: String {
        return "\(firstName ?? "") \(lastName ?? "")"
    }
}

class AuthenticatedUserModel: UserModel {
    let accessToken: String?
    
    override init(id: Int, firstName: String, lastName: String, bio: String) {
        self.accessToken = nil
        super.init(id: id, firstName: firstName, lastName: lastName, bio: bio)
    }
}
3
  • I believe it's because AuthenticationModel adds more fields, so the codable initializer that UserModel has would not work with the new model. Commented Jan 17, 2022 at 15:41
  • However, you've got so many optional fields, that I think you would be better served with a polymorphic model. I wrote an article on that here Commented Jan 17, 2022 at 15:41
  • Off-topic but maybe you could move some of all those properties into separate types if the belong together (like the ones related to follow) and/or maybe some of the Bool properties can be grouped together into an enum? And do you really need a sub class, is it for users that need to authenticate or what is the difference between it and a normal (superclass) user? All rhetorical questions for you to consider. Commented Jan 17, 2022 at 15:48

1 Answer 1

1

The Decodable protocol requires the implementation of the method init(from:). Cause of adding a new property the automatically created init(from:) method of the parent class is not inherited. This happens cause the inherited method can not initialize the new property from the child class.

Therefore the solution is to add the required method. For example like this (untested code)

required init(from decoder: Decoder) throws {
    accessToken = try decoder.singleValueContainer().decode(String.self)
    try super.init(from: decoder)
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, This was the answer I was looking for and makes total sense.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.