可选关闭并检查它是不是为 nil
Posted
技术标签:
【中文标题】可选关闭并检查它是不是为 nil【英文标题】: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'
【问题讨论】:
【参考方案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
设为可选(因为如果存在闭包,您可能总是传递 true
或 false
的 success
值)。显然,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 类时,有人深思熟虑地忽略了多年在这个项目中。以上是关于可选关闭并检查它是不是为 nil的主要内容,如果未能解决你的问题,请参考以下文章