1
votes

I am trying to implement Codable with Coredata. I've tried following the following answer, but still have had no luck.

How to use swift 4 Codable in Core Data?

The error/problem I am having is my project is continuing to say: "Argument type 'User' does not conform to expected type 'Encodable' whenever I try to encode or decode the object.

I have created the Entity in CoreData and made NSManagedObject subclasses:

import Foundation
import CoreData

@objc(User)
public class User: NSManagedObject, Codable {

// MARK: - Codable setUp
enum CodingKeys: String, CodingKey {
    case fullname
    case email
    case zipcode
    case usertype = "user_type"
}


// MARK: - Decoding the data
required convenience init(from decoder: Decoder) {
    guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else {NSLog("Error: with User context!")
        return
    }

    guard let entity = NSEntityDescription.entity(forEntityName: "User", in: context) else {
        NSLog("Error with user enity!")
        return
    }

    self.init(entity: entity, in: context)

    let values = try decoder.container(keyedBy: CodingKeys.self)
    fullname = try values.decode(String.self, forkey: .fullname)
    email = try values.decode(String.self, forkey: .email)
    zipcode = try values.decode(String.self, forkey: .zipcode)
    userType = try values.decode(String.self, forkey: .userType)

}

// MARK: - Encoding the data
func encode(to encoder: Encoder) throws {
    var container = try encoder.container(keyedBy: CodingKeys.self)

    try container.encode(fullname, forkey: .fullname)
    try container.encode(email, forkey: .email)
    try container.encode(usertype, forkey: .usertype)
    try container.encode(zipcode, forkey: .zipcode)
}


}

// This helps with decoding
extension CodingUserInfoKey {
   static let context = CodingUserInfoKey(rawValue: "context")
}

When I try to decode the object and save the user to firebase I get a warning that says "In argument type 'User.Type', 'User' does not conform to expected type 'Decodable'

When I try to encode I get a warning that says "Argument type 'User' does not conform to expected type 'Encodable'

2
Your code gives different errors in a playground. It says your init and encode methods must be declared public because your User class is public. Are you not getting those errors?Mike Taverne

2 Answers

0
votes

User' does not conform to expected type 'Decodable

occurs due to a typo (case sensitivity matters):

case usertype ... vs. ...forKey: .userType)

and the encode/decode(:forKey:) methods have a capital K

0
votes

Your Problem might not be related to CoreData/Codable, but rather to an imported User model, that in fact does not conform to Codable.

Firebase defines a User in their FirebaseAuth.framework (Reference). If you import Firebase at the top of your file, it will also import that User declaration. IMO this is bad API design by Firebase, because many apps that also use FirebaseAuth will have a User model with some custom properties at some point...

If you don't need FirebaseAuth in that file, just import the more specific Firebase framework, e.g. import FirebaseDatabase to avoid importing their User model.

Otherwise, to help the compiler selecting your User model instead of the imported model, you can explicitly prepend User.self with your module name: YourModule.User.self.