18
votes

I am working on mix and match iOS source code. I have implemented codable for swift data model class which reduces the burden of writing parser logic. I tried to conform my objective c class to codable protcol which in turn thrown an error "Cannot find protocol declaration for 'Codable'". Is there any way to use this swift protocol into objective c class? Or Is there any other objective c api that provides the same capability as Codable? The idea is to make the parsing logic same across swift and objective c classes.

2
NSCoding is the corresponding Objective-C protocol that also was used for Swift before Codable was introduced - Joakim Danielson
@JoakimDanielson - Conforming to NSCoding protocol, custom class objects can be serialized/deserialized to archive/unarchive. Will this help to parse jsonobject to custom type or vice versa? - myCmyL
No. You can't. Codable is only available to Swift only. And there is no counter-part for Objective-C, because if there was one then why introducing Codable after all? - nayem
Read Jordan Rose's explanation, Why You Cant Make Someone Else's Class Decodable, which touches on how required initializers and subclasses make for Problems with non-final data structures. ObjC does not have final, so those reasons apply to the current poster's question as well. - AmitaiB

2 Answers

13
votes

Yes, you can use Codable together with Obj-C. The tricky part is that because Obj-C can't see Decoder, so you will need to create a helper class method when you need it to be allocated from Obj-C side.

public class MyCodableItem: NSObject, Codable {
    private let id: String
    private let label: String?

    enum CodingKeys: String, CodingKey {
        case id
        case label
    }

    @objc public class func create(from url: URL) -> MyCodableItem {
        let decoder = JSONDecoder()
        let item = try! decoder.decode(MyCodableItem.self, from: try! Data(contentsOf: url))
        return item
    }

    public required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(String.self, forKey: .id)
        label = try? container.decode(String.self, forKey: .label)
        super.init()
    }

    required init(coder decoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
2
votes
class LoginDataModel: NSObject ,Codable {
 @objc var stepCompleted: String?
 @objc var userID: Int?
 @objc var authkey: String?
 @objc var type, status: String?


 enum CodingKeys: String, CodingKey {
    case stepCompleted = "step_completed"
    case userID = "user_id"
    case authkey
    case type, status
  }
}