【问题标题】:optional closure and check if it is nil可选关闭并检查它是否为 nil
【发布时间】:2014-11-25 12:41:39
【问题描述】:

所以我想要的是一个可以在函数中将闭包传递给它的类,它也可能在某些时候想要忽略该闭包。如何检查闭包变量是否已设置,完成后如何将其删除?

不能使用类型为 '(@lvalue (succsess: Bool!, products: [AnyObject]!) -> ()?, NilLiteralConvertible)' 类型 '(成功:布尔!,产品:[AnyObject]!)->()?不符合 协议'NilLiteralConvertible'

class someClass{
    //typealias completionHandlerClosureType = (sucsess:Bool!, items:[AnyObject]!)->()
    var completionHandler:(sucsess:Bool!, items:[AnyObject]!)->()?
    var hitpoints = 100
    var someset = ["oh no!","avenge me!"]
    init(){}

    func getHitFunc(impact:Int, passedCompletionsHandler:(sucsess:Bool!, items:[AnyObject]!)->()){
        completionHandler = passedCompletionsHandler
        hitpoints = hitpoints - impact
    }

    func checkIfDead{
        if hitpoints<=0 {               // The error received
            if completionHandler != nil{// Cannot invoke '!=' with an argument list of type 
                                        //'(@lvalue (sucsess: Bool!, products: [AnyObject]!) -> ()?, NilLiteralConvertible)' 
                //run the handler if dead
                completionHandler(sucsess: true, items: someset)
                //do not run it again
                completionHandler = nil     //Type '(sucsess: Bool!, products: [AnyObject]!) -> ()?' does not conform to protocol 'NilLiteralConvertible'
            }
        }
        else{
            completionHandler = nil      //Type '(sucsess: Bool!, products: [AnyObject]!) -> ()?' does not conform to protocol 'NilLiteralConvertible'
        }
    }
}

【问题讨论】:

    标签: swift closures block


    【解决方案1】:

    您需要将闭包签名包装在括号中,以使闭包本身是可选的。按照现在的写法,闭包返回一个可选的 Void(这实际上没有意义)。

    var completionHandler: ((sucsess:Bool!, items:[AnyObject]!)->())?
    

    您的示例代码的一些样式点和修订:

     // Capitalize class names so it's clear what's a class 
    class SomeClass {
        // "success" has two "c"s
        var completionHandler: ((success:Bool!, items:[AnyObject]!)->())?
        var hitpoints = 100
        var someset = ["oh no!","avenge me!"]
    
        init() { }
    
        func getHitFunc(impact:Int, passedCompletionsHandler:(success:Bool!, items:[AnyObject]!)->()){
            completionHandler = passedCompletionsHandler
            hitpoints = hitpoints - impact
        }
    
        // You were missing the argument list here:
        func checkIfDead() {
            if hitpoints <= 0 {
    
                // Rather than checking to see if the completion handler exists, you can
                // just call it using optional syntax like this:
                completionHandler?(success: true, items: someset)
            }
            completionHandler = nil
        }
    }
    

    【讨论】:

      【解决方案2】:

      首先,在完成处理程序的声明中,您需要使用括号将整个内容声明为可选:

      var completionHandler: ((_ success: Bool, _ items: [Any]?) -> ())?
      

      或者,也许更好,您可以将最后的 () 替换为 Void

      var completionHandler: ((_ success: Bool, _ items: [Any]?) -> Void)?
      

      另外,请注意,我不认为您打算将 Bool 设为可选(因为如果存在闭包,您可能总是传递 truefalsesuccess 值)。显然,items 的数组很可能是可选的。

      无论如何,完成后,您只需确保打开该可选选项:

      func checkIfDead() {
          if hitpoints <= 0 {
              completionHandler?(true, items)
          }
          completionHandler = nil
      }
      

      当且仅当它不是nil 时才会执行闭包,避免需要显式检查它是否是nil


      对于它的价值,这可能是您的typealias 可能会使这不那么混乱的情况:

      typealias CompletionHandlerClosureType = (_ success: Bool, _ items: [Any]?) -> Void
      

      那么属性就是:

      var completionHandler: CompletionHandlerClosureType?
      

      将此completionHandler 作为可选参数的函数可以这样做:

      func startSomeProcess(passedCompletionHandler: CompletionHandlerClosureType?) {
          completionHandler = passedCompletionHandler
          // do whatever else you want
      }
      

      然后最后的完成逻辑不变:

      func finishSomeProcess() {
          completionHandler?(true, items)
          completionHandler = nil
      }
      

      (请注意,以上内容已针对 Swift 3 进行了修改。如果您想查看 Swift 2 版本,请参阅此答案的 previous revision。)

      【讨论】:

      • 类型别名是很好的解决方案
      • 这个解释太棒了。仍然适用于 Swift 4。完成块在 swift 中比 Objective-C 有了很大改进,但仍然需要一些努力才能使其正确,特别是当我移植过去的几个 Objective-C 类时,有人深思熟虑地忽略了多年在这个项目中。
      猜你喜欢
      • 1970-01-01
      • 2015-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 2014-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多