在 Swift 中将可选绑定转换为错误处理的过程是啥?

Posted

技术标签:

【中文标题】在 Swift 中将可选绑定转换为错误处理的过程是啥?【英文标题】:What is the process to translate optional binding into error handling in Swift?在 Swift 中将可选绑定转换为错误处理的过程是什么? 【发布时间】:2018-07-02 19:29:50 【问题描述】:

我正在学习使用 Locksmith 框架存储令牌的 OAuth 教程。本教程是用旧版本的 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
        
    

【问题讨论】:

【参考方案1】:

我认为这里的主要问题是原始代码没有处理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
    

【讨论】:

【参考方案2】:
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
    

【讨论】:

以上是关于在 Swift 中将可选绑定转换为错误处理的过程是啥?的主要内容,如果未能解决你的问题,请参考以下文章

无法在 swift 中将常量声明为可选?

Swift 模式匹配 - 在单个语句中切换、向下转换和可选绑定

与 try 的可选绑定?并作为?仍然产生一个可选类型

如何在 Swift 的绑定中解开可选值?

任何不一致的铸造?在可选绑定期间进入 Swift 中的协议

如何在 Swift 中将十六进制字符串转换为 CString?