Как происходит преобразование необязательного связывания в обработку ошибок в Swift? - PullRequest
0 голосов
/ 02 июля 2018

Я работаю над учебником OAuth, в котором для хранения токенов используется среда Locksmith. Учебник написан в более старой версии Swift, а также со старой версией фреймворка Locksmith. При воссоздании примера в Swift 4 я заметил, что Locksmith 4.0 использует обработку ошибок с блокировками do try catch. Я пытаюсь перевести необязательную привязку руководства в использование подхода обработки ошибок в рамках. Сначала я попробовал сам, но у меня возникли проблемы с установлением связи между тем, почему в учебнике используется необязательное связывание.

Вот выдержка из учебника:

var OAuthToken: String?
{
  set
  {
    if let valueToSave = newValue
    {
      let error = Locksmith.saveData(["token": valueToSave], forUserAccount: "github")
      if let errorReceived = error
      {
        Locksmith.deleteDataForUserAccount("github")
      }
      addSessionHeader("Authorization", value: "token \(newValue)")      
    }
    else // they set it to nil, so delete it
    {
      Locksmith.deleteDataForUserAccount("github")
      removeSessionHeaderIfExists("Authorization")
    }
  }
  get
  {
    // try to load from keychain
    let (dictionary, error) = Locksmith.loadDataForUserAccount("github")
    if let token =  dictionary?["token"] as? String {
      return token
    }
    removeSessionHeaderIfExists("Authorization")
    return nil
  }
}

Вот что у меня есть. Я полагаю, что неправильно использую оператор catch в отношении необязательного связывания:

var OAuthTokenCompletionHandler: ((NSError?) -> Void)?

    var authToken: String? {
        set {
            if let valueToSave = newValue{
                do{
                try Locksmith.saveData(data: ["token" : valueToSave], forUserAccount: "AzureMediaServices")
                } catch {
                    //could not save the data into keychain
                    //handle the error somehow
                    try Locksmith.deleteDataForUserAccount(userAccount: "AzureMediaServices")
                }

                addSessionHeader("Authorization", value: "Bearer \(valueToSave)")
            } else {
                //try to set it to nil
                removeSessionHeaderIfExists("Authorization")
            }
        }
        get {
            //TODO: implement
        }
    }

Ответы [ 2 ]

0 голосов
/ 28 июля 2018
var OAuthToken: String? {
    set {
        guard let newValue = newValue else {
            let _ = try? Locksmith.deleteDataForUserAccount(userAccount: "github")
            return
        }
        guard let _ = try? Locksmith.updateData(data: ["token": newValue],
                                                forUserAccount: "github") else {
                                                    let _ = try? Locksmith.deleteDataForUserAccount(userAccount: "github")
                                                    return
        }
    }
    get {
        // try to load from keychain
        let dictionary = Locksmith.loadDataForUserAccount(userAccount: "github")
        return dictionary?["token"] as? String
    }
}
0 голосов
/ 02 июля 2018

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

Вот мой первый удар:

var OAuthTokenCompletionHandler: ((NSError?) -> Void)?

var authToken: String? {
    set {
        guard let valueToSave = newValue else {
            do {
                try Locksmith.deleteDataForUserAccount(userAccount: "AzureMediaServices")
            }
            catch {
                // handle the error somehow
            }

            removeSessionHeaderIfExists("Authorization")
            return
        }

        do{
            try Locksmith.saveData(data: ["token" : valueToSave], forUserAccount: "AzureMediaServices")
        } catch {
            do {
                try Locksmith.deleteDataForUserAccount(userAccount: "AzureMediaServices")
            }
            catch {
                // handle the error somehow
            }
        }

        addSessionHeader("Authorization", value: "Bearer \(valueToSave)")
    }
    get {
        guard let token = Locksmith.loadDataForUserAccount("github")?["token"] as? String {
            removeSessionHeaderIfExists("Authorization")
            return nil
        }
        return token
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...