Слияние словарей

scorocode
swift
dictionary
alamofire
request

#1

Недавно писал метод для универсального сетевого запроса. При использовании метода, использовался словарик с ключами, которые каждый раз передавались в запросе для идентификации приложения

Каждый раз при вызове метода нужно было формировать тело запроса с кастомными полями и этими ключами, что выглядело как то громоздко. В общем, проблема решается подготовкой словаря с последующем добавлением к нему словаря ключей уже внутри метода запроса к серверу.

Может кому пригодится расширение стандартного словаря:

extension Dictionary {
  
  mutating func merge(with dictionary: Dictionary) {
    dictionary.forEach { updateValue($1, forKey: $0) }
  }
  
  func merged(with dictionary: Dictionary) -> Dictionary {
    var dict = self
    dict.merge(with: dictionary)
    return dict
  }
   
}

Ну и пример:

let keys = ["appId": "<...>", "clientId": "<...>", "secretKey": "<...>"]
let bodyRequest = ["description": "Bla Bla Bla", "title": "Bla Bla Bla"]
let body: [String : Any] = bodyRequest.merged(with: keys)

На выходе будет:

["description": "Bla Bla Bla", "title": "Bla Bla Bla", "appId": "<...>", "clientId": "<...>", "secretKey": "<...>"]

Ну и пример как формировать такой запрос в Alamofire:

fileprivate func requestToServerPOST(method: RTConfig.RTScorocodeAPI, bodyRequest: [String: Any], callback: @escaping (_ obj: Any?) -> Void) {
    let headers = ["Content-Type": "application/json"]
    let body: [String : Any] = bodyRequest.merged(with: keys)
    let adress = "\(RTConfig.RTScorocodeAPI.baseLink.rawValue)\(method.rawValue)"
    Alamofire.request(adress, method: .post, parameters: body, encoding: JSONEncoding.default, headers: headers)
      .authenticate(user: "", password: "***** Hidden credentials *****")
      .validate(statusCode: 200..<300)
      .responseJSON { response in
        if (response.result.error == nil) {
          callback(response.result.value)
        } else {
          debugPrint("HTTP Request failed: \(response.result.error)")
          callback(nil)
        }
    }
  }

А так как недавно мелькал вопрос по работе с данными в Alamofire, их можно мапить:

func insertStationToServer(callback: @escaping (_ _id: String) -> Void) {
    let body: [String : Any] = [
      "coll": "stations",
      "doc": ["station": "INSERT new", "url": "http://swiftbook.ru"]
    ]
    requestToServerPOST(method: .insert, bodyRequest: body) { response -> Void in
      if response != nil {
        if JSONSerialization.isValidJSONObject(response!) {
           if let station = Mapper<RTScorocodeStation>().map(JSONObject: response) {
            print("[STATION ID] = \(station._id!)")
          }
        }
      }
    }
  }

Про маппинг здесь уже обсуждалось, свои модельки сами реализуете!