Evgeniy Kleban
Evgeniy Kleban

Reputation: 6940

Understanding Swift map syntax

I study code, and have Event object:

typealias AnyDict = [String: Any]

class Event {
  let repo: String
  let name: String
  let imageUrl: URL
  let action: String

  // MARK: - JSON -> Event
  init(dictionary: AnyDict) {
    guard let repoDict = dictionary["repo"] as? AnyDict,
      let actor = dictionary["actor"] as? AnyDict,
      let repoName = repoDict["name"] as? String,
      let actorName = actor["display_login"] as? String,
      let actorUrlString = actor["avatar_url"] as? String,
      let actorUrl  = URL(string: actorUrlString),
      let actionType = dictionary["type"] as? String
      else {
        fatalError()
    }

    repo = repoName
    name = actorName
    imageUrl = actorUrl
    action = actionType
  }

  // MARK: - Event -> JSON
  var dictionary: AnyDict {
    return [
      "repo" : ["name": repo],
      "actor": ["display_login": name, "avatar_url": imageUrl.absoluteString],
      "type" : action
    ]
  }
}

In my viewController class i have code that load data from Api and fill output Events object models. Complete code look like that:

let response = Observable.from([repo])
        .map { urlString -> URL in
            return URL(string: "https://api.github.com/repos/\(urlString)/events")!
    }
        .map { url -> URLRequest in
            return URLRequest(url: url)
    }
        .flatMap { request -> Observable<(HTTPURLResponse, Data)> in
            return URLSession.shared.rx.response(request: request)
    }
    .shareReplay(1)

    response
        .filter { response, _ in
            return 200..<300 ~= response.statusCode
    }
        .map { _, data -> [[String: Any]] in
            guard let jsonObject = try? JSONSerialization.jsonObject(with: data,
                                                                     options: []),
                let result = jsonObject as? [[String: Any]] else {
                    return [] }
            return result
    }
        .filter { objects in
            return objects.count > 0
    }
        .map { objects in
            return objects.map(Event.init)
    }
        .subscribe(onNext: { [weak self] newEvents in
            self?.processEvents(newEvents)
        })
        .disposed(by: bag)

My question is - i don't understand meaning of :

.map { objects in
            return objects.map(Event.init)

I realize that somehow that piece of code give us Event objects from [String: Any] object.

But i dont understand objects.map(Event.init). For me, in map we should perform actions with corresponding type, something like { Event.init(with: $0) } or something like that. What is meaning of objects.map(Event.init)? And how does it work?

Upvotes: 1

Views: 442

Answers (1)

Sweeper
Sweeper

Reputation: 271625

map(Event.init) and map({Event.init(with: $0)}) are equivalent.

Think of it this way, map requires a closure that takes something of type T and return something of type U. {Event.init(with: $0)} is such a closure (takes an argument $0, creates a new Event and returns it), so you can pass it in.

But don't forget that methods and initialisers are also a type of closure. The initializer of Event, which takes one argument and returns an Event is compatible with what the map method needs! So instead of passing a closure using the {} syntax, you can just say "use the initializer of Event!" by doing: map(Event.init)

Upvotes: 3

Related Questions