2014-09-30 37 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