2014-09-30 70 views
39

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

不能调用 '!=' 类型的参数列表 '(@lvalue(sucsess: 布尔!,产品:[AnyObject]) - >()?NilLiteralConvertible)' 类型“(sucsess :Bool !,产品:[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' 
     } 
    } 
} 

回答

38

你需要用你的闭合签名括号使盖子本身可选的。现在写它的方式,闭包返回一个可选的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 
    } 
} 
39

首先,在你完成处理的声明,你需要声明与使用括号可选整个事情:

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

此外,请注意,我不认为你的意思是让Bool可选的(因为如果关闭存在,你可能总是通过一个success的值为truefalse)。显然,items可能是可选的。

反正完成时,你只要确保打开那可选:

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

此进行封闭,当且仅当它是不是nil,避免需要明确检查,如果它是nil


对于它的价值,这可能是在您的typealias可能使这种容易混淆的情况下:

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

则该属性很简单:

var completionHandler: CompletionHandlerClosureType? 

,是以功能这个completionHandler作为一个可选参数可以做到:

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

,然后最终完成逻辑是不变的:

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

(注意,上面已被修改为雨燕3.请参阅本答案的previous revision如果你想看到斯威夫特2引渡。 )

+0

类型别名是伟大的解决方案 – Yitzchak 2017-03-06 15:26:24