Manngo
Manngo

Reputation: 16433

How can I create an instance of a Codable Struct?

I am going round in circles trying to work with a Codable Struct. I can nearly get it to work, but I get an error at the end.

Here is a simple example:

struct Stuff: Codable {
    var title: String = ""
    var code: Int = 0
    struct Item {
        var name: String
        var value: Int
    }
    var items: [Item] = []
    init(from decoder: Decoder) throws { }
    func encode(to encoder: Encoder) throws { }
}

var items: [Stuff.Item] = []

items.append(Stuff.Item(name: "Apple", value: 1))
items.append(Stuff.Item(name: "banana", value: 2))

var stuff = Stuff(title: "test", code: 23, items: items)

On that last line I get the error

Extra arguments at positions #1, #2, #3 in

Clearly the nested struct is OK. If I remove the :Codable and the init() and func encode() it works as I would have expected.

What is the correct way to do this?

Upvotes: 1

Views: 3667

Answers (1)

PGDev
PGDev

Reputation: 24341

Reason:

Since you've implemented init(from:) initialiser, so the default init is not available.

That the reason, it is not able to find init(title:,code:,items:)

Solution:

Implement the initialiser init(title:,code:,items:) manually. Also, conform Item to Codable as well.

Now, the struct Stuff must look like,

struct Stuff: Codable {
    var title: String = ""
    var code: Int = 0
    struct Item: Codable {
        var name: String
        var value: Int
    }
    
    var items: [Item] = []
    init(from decoder: Decoder) throws { }
    func encode(to encoder: Encoder) throws { }
    
    init(title: String, code: Int, items: [Item]) {
        self.title = title
        self.code = code
        self.items = items
    }
}

Upvotes: 6

Related Questions