2015-08-10 3 views
5

Я использую Moya Swift framework для сетевого слоя, который построен поверх Alamofire.Moya/Alamofire - URL-кодированные параметры с теми же клавишами

В настоящее время я пытаюсь отправить запрос с URL-кодированными параметрами, которые имеют одинаковые ключи.

т.е. http://some-site/request?param=v1&param=v2&param=v3

Я уже пытался сгруппировать эти Титулы в набор или NSSet или массив, как это, но ничего не помогает достичь желаемого результата.

["param": ["v1", "v2", "v3"]];

["param": Set(arrayLiteral: "v1", "v2", "v3")]

Любая помощь будет оценена либо с Мойя или с самим Alamofire.

Edit: Вот некоторые примеры кода, чтобы дать основную идею:

установки Api Router

import Moya 

// MARK:- Enum Declaration 

enum ApiRouter { 
    case XAuth(login: String, password: String) 
    case SomeRequest(params: [String]) 
} 

// MARK:- Moya Path 

extension ApiRouter: MoyaPath { 
    var path: String { 
     switch self { 
     case .XAuth: 
      return "/authorization" 
     case .SomeRequest: 
      return "/some-request" 
     } 
    } 
} 

// MARK:- Moya Target 

extension ApiRouter: MoyaTarget { 
    private var base: String { 
     return "http://some-site" 
    } 
    var baseURL: NSURL { 
     return NSURL(string: base)! 
    } 

    var parameters: [String: AnyObject] { 
     switch self { 
     case .XAuth(let login, let password): 
      return [ 
       "email": login, 
       "password": password 
      ] 
     case .SomeRequest(let params): 
      return [ 
       "params": params 
      ] 
    } 

    var method: Moya.Method { 
     switch self { 
     case .XAuth: 
      return .POST 
     case .SomeRequest, 
      return .GET 
     } 
    } 

    var sampleData: NSData { 
     switch self { 
     case .XAuth: 
      return "{}".dataUsingEncoding(NSUTF8StringEncoding) 
     case .ServiceRequests: 
      return "{}".dataUsingEncoding(NSUTF8StringEncoding) 
     } 
    } 
} 

установки Api Provider

let endpointsClosure = { (target: ApiRouter) -> Endpoint<ApiRouter> in 
    let endpoint = Endpoint<ApiRouter>(
     URL: target.baseURL.URLByAppendingPathComponent(target.path).absoluteString!, 
     sampleResponse: EndpointSampleResponse.Success(200, { target.sampleData }), 
     method: target.method, 
     parameters: target.parameters, 
     parameterEncoding: parameterEncoding(target) 
    ) 
    switch target { 
    case .XAuth: 
     return endpoint 
    default: 
     let token = "some-token" 
     return endpoint.endpointByAddingHTTPHeaderFields(["Authorization": "Bearer: \(token)"]) 
    } 
} 

func parameterEncoding(target: ApiRouter) -> Moya.ParameterEncoding { 
    switch target { 
    case .XAuth: 
     return .JSON 
    case .SomeRequest: 
     return .URL 
    } 
} 

let apiProvider = MoyaProvider(endpointsClosure: endpointsClosure) 

apiProvider.request(ApiRouter.SomeRequest(params: ["v1", "v2", "v3"], completion: { (data, statusCode, response, error) in 
    /* ... */ 
}) 

Спасибо.

+0

Можете ли вы указать, ваш API является «GET "или" POST "? –

+0

@ SohilR.Memon это запрос GET –

+0

Можете ли вы разместить код? –

ответ

7

Итак, я нашел решение, которое на самом деле довольно просто и очевидно. документация Чтение Alamofire «s Я нашел это:

Поскольку нет опубликовано спецификации, как кодировать типы коллекций, Alamofire следует условности добавления [] к ключу для значений массива (Foo [] = 1 & foo [] = 2) и добавление ключа, окруженного квадратными скобками для вложенных значений словаря (foo [bar] = baz).

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

Here с тем же вопросом с тем же ответом.

+0

Когда было бы неплохо не использовать Мойю? Существуют ли альтернативы использованию Moya? – user805981

+0

есть много libs, вы называете :) Вы можете использовать Alamofire или NSURLSession и создать свою собственную обертку, есть что-то очень похожее на Moya, и это Swish от Thoughtbot. На самом деле сетевой слой обычно один и тот же, поэтому вы можете посмотреть, как он работает здесь и создать свой собственный. –

+0

@ Voronv Я посмотрел. И что-то, чего не хватает в Moya или другом уровне абстракции сети, - это подход OAuth/JWT запроса на обновление/обновление истекшего токена аутентификации перед запуском следующего запроса. Например, если токен auth истек, токен должен быть обновлен на стороне клиента до следующего запроса moya ... У вас есть рекомендации? – user805981

0

Вы можете просто создать строку, используя формат и передать его в качестве URL запроса:

http://some-site/request?param=v1&param=v2&param=v3

String url: String = String(format: "http://some-site/request?param=%@&param=%@&param=%@", v1, v2, v3) 

Надеется, что это помогает!

4

Moya - хорошая идея, но на самом деле я чувствую, что с некоторым мышлением мы можем построить сетевой абстракционный слой с помощью Swift без особого кода.

Наша цель:

  • Гибкость, чтобы иметь возможность редактировать или добавлять новые конечные точки эффективно
  • читаемость, чтобы иметь хорошее представление о том, как наш API работы с первого взгляда
  • код безопасности, с типизированными параметрами, которые позволят всем требованиям до компиляции (завершение, валидация), которые мы ожидаем от Xcode.
  • Легкая отладка, то есть возможность вставлять журналы до и после того, как веб-запросы

Вот что я закончил с на dummy project:

public class API { 

public static let baseURL: String = "http://colourlovers.com/api" 

public enum Endpoints { 

    case Colors(String) 
    case Palettes(String) 
    case Patterns(String) 

    public var method: Alamofire.Method { 
     switch self { 
     case .Colors, 
      .Palettes, 
      .Patterns: 
      return Alamofire.Method.GET 
     } 
    } 

    public var path: String { 
     switch self { 
     case .Colors: 
      return baseURL+"/colors" 
     case .Palettes: 
      return baseURL+"/palettes" 
     case .Patterns: 
      return baseURL+"/patterns" 
     } 
    } 

    public var parameters: [String : AnyObject] { 
     var parameters = ["format":"json"] 
     switch self { 
     case .Colors(let keywords): 
      parameters["keywords"] = keywords 
      break 
     case .Palettes(let keywords): 
      parameters["keywords"] = keywords 
      break 
     case .Patterns(let keywords): 
      parameters["keywords"] = keywords 
      break 
     } 
     return parameters 
    } 
} 

public static func request(
    endpoint: API.Endpoints, 
    completionHandler: Response<AnyObject, NSError> -> Void) 
    -> Request { 

     let request = Manager.sharedInstance.request(
      endpoint.method, 
      endpoint.path, 
      parameters: endpoint.parameters, 
      encoding: .URL, 
      headers: nil 
      ).responseJSON { response in 

       if (response.result.error) != nil { 
        DDLogError("\n<----\n" + response.result.error!.description) 
        completionHandler(response) 
       } else { 
        DDLogInfo("\n<----\n" + response.response!.description) 
        completionHandler(response) 
       } 
     } 
     DDLogInfo("\n---->\n" + request.description) 
     return request 
    } 
} 
+0

Итак, вы, ребята, не использовали Мойю? – user805981

+0

Мне нравится эта идея. В текущем проекте я работал, сетевой уровень полезен. Приложение не должно касаться 'Alamofire' напрямую. Дополнительный сетевой уровень приобретает большую гибкость, но добавляет больше сложности. – AechoLiu

Смежные вопросы