Search code examples
swiftcodabledecodableencodable

Swift 4 decoding/encoding a generic data structure


I have a generic Queue data structure which utilizes an array as its list, I am having hard time making the queue conform to encodable and decodable. I have another class which uses the queue which also needs to be Codable but it cannot be coddle unless its member variables are.

I have tried conforming the queue to encodable and decodable, encoding the data and saving it to user defaults but this does not seem to be working, in fact my init(from decoder) function is even stuck in an infinite loop for whatever reason. I could really use some assistance

//My Queue

public struct Queue<T: Codable> {

    private var dataSource  = [T]()
    private var userDefaults = UserDefaults()
    public init() {}


    public func isEmpty() -> Bool{

        return  dataSource.isEmpty
    }

    public mutating func enqueue( element: T){
        dataSource.append(element)
   }

   public mutating func dequeue() -> T?{
        return isEmpty() ? nil : dataSource.removeFirst()
    }

    public func peek() -> T? {
        return isEmpty() ? nil : dataSource.first
    }

    public func getCount() -> Int {
        return dataSource.count
    }

    public func printQueue(){
        print(dataSource)
    }
}





public enum Error: String, Swift.Error{
    case queueNotFound = "Queue Not Found!"
}

extension Queue: Encodable, Decodable {
    public func encode(to encoder: Encoder) throws
    {
        let jsonEncoder = JSONEncoder()
        let encodedData = try  jsonEncoder.encode(dataSource)
        userDefaults.set(encodedData, forKey: "queue")
        print(encodedData)
        //var container = encoder.container(keyedBy: CodingKey.self)
    }

    public init(from decoder: Decoder) throws
    {
     print("intilaizing")
        let jsonDecoder = JSONDecoder()
        guard let data = userDefaults.data(forKey: "queue"), let _ =         try? jsonDecoder.decode(Queue.self, from: data)
            else {
                throw Error.queueNotFound
        }

    }

Any class should be able to addd this queue as a data member, when I implement the queue the encode function works I believe but the decoder causes some infinite loop


Solution

  • You are encoding dataSource – which is [T] – but are decoding Queue, this cannot work. Try

    public init(from decoder: Decoder) throws
    {
        print("initializing")
        guard let data = userDefaults.data(forKey: "queue") else { throw Error.queueNotFound }
        dataSource = try JSONDecoder().decode([T].self, from: data)
    }
    

    By the way in your code the decoded value – as well as a potential DecodingError – is unused which makes no sense.