2016-11-29 29 views
1

我的應用使用具有短期滿計時器的訪問令牌在進行服務器調用時對用戶進行身份驗證。當使用過期令牌進行呼叫時,服務器以402狀態作出響應,並且用戶必須發送刷新令牌,以提示服務器發送新的訪問令牌。然後,我需要使用與首先完全相同的參數進行相同的服務器調用,但現在使用我的新訪問令牌。我怎樣才能使這個過程自動化,以便令牌交換髮生,並且我們獲得了我們最初想要的資源,而沒有任何用戶輸入(即它都發生在後臺,用戶甚至沒有意識到)?我想不出不涉及製造可怕的嵌套調用,像這樣的方式:如何爲令牌交換創建遞歸回調,Swift

someAPICall(foo, arg2: bar) { result, error in 
    if let result = result { 
     if result.status == 402 { 
      performTokenExchange(refreshToken) { newAccessToken, error in 
       if newToken { 
        someAPICall(foo, bar) { result, error in 
         //... 
        } 
       } 
      } 
     } 
     else { 
      // ... continue with program 
     } 
    }  
} 

我首先想到的是把遞歸進入畫面,並遞歸調用「someAPICall」中的「performTokenExchange」回調中,但後來我不知道如何處理「someCall」而沒有在「performTokenExchange」回調中明確地管理它,讓我回到我的「可怕的嵌套呼叫」問題。

+0

因此'someAPICall'是一個給定的函數,你不寫自己,但只能調用並傳遞完成閉包?我問,因爲你已經在函數名稱前面使用過'func'。 – Keiwan

+0

@Keiwan哎呀!我的錯誤 - 意味着顯示「someAPICall」的一個實例。它是我自己編寫的一個函數 - 編輯我的代碼以顯示。 –

回答

1

雖然我自己沒有嘗試過,但我認爲在編寫閉包時應該能夠使用遞歸,然後在調用它時將它作爲參數傳遞給函數。

var completion: ((Result?, Error?) -> Void)! // change this to whatever types your result and error are 

completion = { result, error in 

    if let result = result { 
     if result.status == 402 { 

      performTokenExchange(refreshToken) { newToken, error in 
       if newToken { 
        someAPICall(foo, bar, completion) 
       } 
      } 
     } else { 
      // ... continue with program 
     } 
    } 
} 

所以你首先聲明你的完成閉包作爲一個隱式解包可選與它的特定類型。然後,您可以將實際的代碼塊分配到completion,您可以再次參考completion,因爲它是事先聲明的。

這樣,你應該能夠使API調用,如:

someAPICall(foo, bar, completion) 

(就像它也被用來關閉自身內部)

讓我知道這是否正常工作! 如上所述,這只是一個想法,沒有測試:)

+0

哦,這真棒哈哈我會給它一個裂縫,並更新你!這看起來像是那些可選的Swift應該做的事情 –