2016-05-09 2 views
8

Я хотел бы реализовать метод цепочки в моем swift код, вероятно, Alamofire методов. Например, если я использовать свою функцию, как показано нижеSwift - Метод цепочки

getListForID(12).Success { 
    // Success block 
}. Failure { 
    // Failure block 
} 

Как я хотел бы создать функцию getListForID?

+0

Вы можете вернуть объект, который имеет '' success' и failure' собственность и 'success' сеттер также возвращает, что, кстати вы можно использовать promiseKit, что делает его http://promisekit.org/ –

+0

Вы можете попробовать мою статью, которая делает именно это: [СЦЕПЛЕНИЕ асинхронных функций в Swift] (https://medium.com/@jhoomuck/composing-asynchronous-functions- в-Свифта-acd24cf5b94a) – zeitgeist7

ответ

7

Чтобы увеличить на большие точки @dasblinkenlight и @Sulthan сделали - вот небольшой пример того, как вы могли бы достичь своей функции запроса, чтобы добиться успеха и сбоя, в удобном синтаксисе, который вы хотите.

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

class ResultHandler { 

    typealias SuccessClosure = RequestHandler.Output->Void 
    typealias FailureClosure = Void->Void 

    // the success and failure callback arrays 
    private var _successes = [SuccessClosure]() 
    private var _failures = [FailureClosure]() 

    /// Invoke all the stored callbacks with a given callback result 
    func invokeCallbacks(result:RequestHandler.Result) { 

     switch result { 
      case .Success(let output): _successes.forEach{$0(output)} 
      case .Failure: _failures.forEach{$0()} 
     } 
    } 

    // remove all callbacks – could call this from within invokeCallbacks 
    // depending on the re-usability of the class 
    func removeAllCallbacks() { 
     _successes.removeAll() 
     _failures.removeAll() 
    } 

    /// appends a new success callback to the result handler's successes array 
    func success(closure:SuccessClosure) -> Self { 
     _successes.append(closure) 
     return self 
    } 

    /// appends a new failure callback to the result handler's failures array 
    func failure(closure:FailureClosure) -> Self { 
     _failures.append(closure) 
     return self 
    } 
} 

Это позволит определить несколько укупорочных успеха или неудач, которые будут выполняться по завершению работы. Если на самом деле вам не нужна емкость для нескольких закрытий, то вы можете упростить класс, сократив массивы, и просто отслеживая последние добавленные блоки успеха и отказа.

Теперь все, что вам нужно сделать, это определить функцию, которая генерирует новый ResultHandler экземпляр, а затем делает данный асинхронный запрос, с помощью способа invokeCallbacks быть вызван после завершения:

func doRequest(input:Input) -> ResultHandler { 
    let resultHandler = ResultHandler() 
    doSomethingAsynchronous(resultHandler.invokeCallbacks) 
    return resultHandler 
} 

Теперь вы можете называть это как это:

doRequest(input).success {result in 
    print("success, with:", result) 
}.failure { 
    print("fail :(") 
} 

Единственное, что нужно отметить, это ваша doSomethingAsynchronous функции будет направить его завершение блока обратно в основной поток, чтобы обеспечить безопасность потока.


Полный проект (с добавленным пример по использованию): https://github.com/originaluser2/Callback-Closure-Chaining

5

Для того, чтобы понять, что происходит, это помогло бы переписать код без «удобства» синтаксис, который позволяет опускать скобки, когда закрытие последнего параметра функции:

getListForID(12) 
    .Success({ /* Success block */ }) 
    .Failure({ /* Failure block */ }) 

Это делает структуру кода позади этого API более ясным:

  • возвращаемое значение getListForID должно быть объектом
  • объект должен иметь две функции называются Success и Failure*
  • Оба Success и Failure нужно принимать один параметр типа закрытия
  • Оба Success и Failure необходимость вернуть self

* Объект может иметь только Success функцию, и вернуть другой объект с помощью одной функции Failure, но тогда вы не смогли бы переупорядочить обработчики Success и Failure или опустить Success обработчик всего.

+0

Кроме того, одна из возможных реализаций является простой оболочкой для двух массивов - один массив обработчиков успеха и один массив обработчиков отказов, когда 'Success' и Методы 'Failure' просто добавляют параметр к данному массиву. – Sulthan

+0

@Sulthan Абсолютно! Я попытался объяснить синтаксис, не вдаваясь в подробности о том, что произойдет * внутри * методов 'Success' и' Failure'. Оба метода предполагают закрытие в качестве аргумента; что делать с этими закрытиями зависит от реализации метода, хотя хранение замыканий в отдельных массивах для будущего использования имеет смысл. – dasblinkenlight

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