3

Struct

I tried to recreate the codes in demo given by Chris Edihoff in dotSwift 2016 Demo. Here is the code.

struct List {
    let name:String
    let id:Int
}

extension List {
    init?(json: [String:AnyObject]) {
        guard
            let name = json["name"] as? String,
            let id = json["id"] as? Int else
        {
            return nil
        }
        self.name = name
        self.id = id
    }
}

let listData = json["data"] as? [[String:AnyObject]]

Everything seems fine till now. But this is where the problem comes. He did something like this:

let list:[List] = listData.flatMap(List.init)

The above line is supposed to be returning Array of List Objects. Chris Edihoff seems to be doing it without any problem, but when I do that Xcode warns

- flatMap produces 'U?', not the expected contextual result type '_?

Also what is List.init here? I have never seen this way of initialisation of object. It should be List() or if we are using customer initialization here, it should be List(json:someObject) right?

Reference to Chris Edihof Talk: https://www.youtube.com/watch?v=ewk-XNzXzAA

Prajeet Shrestha
  • 7,978
  • 3
  • 34
  • 63

1 Answers1

7

There are different reasons why this code does not compile. First of all, there is no need for you to subscript json["data"] - it's going to be flatMap's job to iterate over that data and initialize the lists.

I see that in the original presentation, listData.flatMap follows a if let block; meaning listData will be unwrapped and not nil.

In your code, instead, you have let listData = json as? [[String:AnyObject]]. Your listData is an optional of type [[String:AnyObject]]?.
So, the way to solve this issue is:

if let listData = json as? [[String:AnyObject]] {
   let list = listData.flatMap(List.init)
   //do something with list
}

Here, listData is of the correct type: [[String: AnyObject]].

Regarding List.init, it is simply a way of explicitly applying the initializer to whatever flatMap provides. You can rewrite that function in a more verbose - but probably clearer - way:

listData.flatMap {data in List(json: data)}
Smnd
  • 1,579
  • 11
  • 7