2016-05-09 16 views
8

Chciałbym zastosować metodę łańcuchową w moim kodzie swift, prawdopodobnie na Alamofire. Na przykład, jeśli muszę korzystać z funkcji takich jak poniżejSwift - Metoda łańcuchowa

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

Jak utworzyć funkcję getListForID?

+0

Można powrócić do obiektu, który ma '' success' i mienia failure' i 'success' setter zwraca również, że btw jesteś można użyć promiseKit, który to robi http://promisekit.org/ –

+0

Możesz wypróbować mój artykuł, który robi właśnie to: [Funkcje łączenia asynchronicznego w Swift] (https://medium.com/@jhoomuck/composing-asynchronous-functions- in-swift-acd24cf5b94a) – zeitgeist7

Odpowiedz

7

Aby rozwinąć wspaniałe punkty: @dasblinkenlight i @Sulthan dokonano - oto mały przykład, w jaki sposób można osiągnąć funkcję żądania, aby odnieść sukces i zamknięcie awarii, w wygodnej składni, którą chcesz.

Najpierw musisz zdefiniować nową klasę, która będzie reprezentować "procedurę obsługi wyników". To właśnie będą przechodzić funkcje success i failure, co pozwala dodawać wiele końcowych zamknięć w celu uzupełnienia logiki bloku zakończenia. Będziemy chcieli to wyglądać mniej więcej tak:

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 
    } 
} 

To pozwoli na zdefiniowanie wielu sukces lub niepowodzenie zamknięcia zostanie zawarta w dniu zakończenia. Jeśli w rzeczywistości nie potrzebujesz zdolności do wielokrotnego zamykania, możesz uprościć klasę, usuwając tablice - i zamiast tego po prostu śledź ostatnie dodane bloki sukcesów i niepowodzenia.

Teraz wszystko co musisz zrobić, to określić funkcję, która generuje nowy ResultHandler instancji, a następnie robi danego żądania asynchronicznego, przy czym metoda invokeCallbacks jest wywoływana po zakończeniu:

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

Teraz można nazwać to jak to:

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

Jedyną rzeczą, aby pamiętać, to funkcja doSomethingAsynchronous będzie miał do wysłania jej zakończenia blok z powrotem do głównego wątku, w celu zapewnienia bezpieczeństwa wątku.


Pełny projekt (z dodatkiem przykład na wykorzystanie): https://github.com/originaluser2/Callback-Closure-Chaining

5

Aby zrozumieć, co się dzieje, że to pomoże przepisać kod bez „convenience”, składni które pozwala pominąć nawiasy kiedy zamknięcie jest ostatni parametr funkcji:

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

to sprawia, że ​​struktury kodu za tym API bardziej jasne:

  • wartość zwracana getListForID musi być przedmiotem
  • obiekt musi mieć dwa funkcję o nazwie Success i Failure*
  • Zarówno Success i Failure trzeba wziąć jeden parametr typu zamknięcia
  • Zarówno Success i Failure konieczność powrotu self

* Obiekt może mieć tylko Success funkcji i zwróć inny obiekt za pomocą pojedynczej funkcji Failure, ale wtedy nie będzie można ponownie zamówić programów obsługi Success i Failure, ani nie upuścić Success całkowicie.

+0

Jedną z możliwych implementacji jest proste opakowanie dla dwóch tablic - jedna tablica programów obsługi sukcesu i jedna tablica obsługi niepowodzeń, gdy "Sukces" i Metody 'Failure 'po prostu dodają parametr do podanej tablicy. – Sulthan

+0

@Sulthan Absolutnie! Próbowałem wyjaśnić składnię, bez wchodzenia w szczegóły co do tego, co się stanie * wewnątrz * metod 'Sukces' i' Awaria'. Obie metody zamknęłyby się jako argument; co zrobić z tymi zamknięciami, zależy od implementacji metod, chociaż przechowywanie zamknięć w osobnych tablicach do przyszłego użycia ma sens. – dasblinkenlight

Powiązane problemy