func foo(){ print("foo") }var bar: () -> () = { print("bar") }var baz: () -> (Bool) = { print("baz"); return true }print(foo) // (Function)print(bar) // (Function)print(baz) // (Function)print(foo is () -> ()) // trueprint(bar is () -> ()) // trueprint(baz is () -> ()) // falseprint(baz is () -> (Bool)) // true
Swift知道它们都是函数,尽管没有这样的数据类型.我可以使用可靠的签名进行检查,但可能存在我不关心签名*并且只是想调用它的情况.例如:
func call(callable: () -> ()) { callable()}call(foo) // foocall(bar) // barcall(baz) // error: cannot convert value of type '() -> (Bool)' to expected argument type '() -> ()'
我可以像这样重写它,它适用于VoID和Bool返回类型,但是为每种类型执行此 *** 作都很疯狂,特别是因为我不关心它,但编译器确实……
func call(callable: Any) { if let block: () -> () = callable as? () -> () { block() } else if let block: () -> (Bool) = callable as? () -> (Bool) { block() }}call(foo) // foocall(bar) // barcall(baz) // truely baz
*同意,不关心签名是罪.为了论证,我们不关心返回类型.
解决方法 您可以检查可调用的.dynamicType的字符串表示是否存在子字符串 – >.不是超级优雅,但它有效:func isAClosure<T>(foo: T) -> Bool { return String(foo.dynamicType).containsstring("->")}var a : () -> () = { print("Foobar") }var b : (Double) -> (Bool) = {/* Example functions */func isAVoIDParamClosure<T>(foo: T) -> Bool { let bar = String(foo.dynamicType).componentsSeparatedByString(" -> ") return bar.count > 1 && (bar.first?.characters.count ?? 0) == 2}func callifVoIDVoIDClosure<T>(foo: T) { let bar = String(foo.dynamicType).componentsSeparatedByString(" -> ") if bar.count > 1 && !(bar.map{> 0 }var c : Int = 1isAClosure(a) // trueisAClosure(b) // trueisAClosure(c) // false/* Example calls */let a : () -> () = { print("Foobar") }let b : (Double) -> (Bool) = { > 0 }let c : () -> Double = { 21.0 }let d : Int = 1isAVoIDParamClosure(a) // trueisAVoIDParamClosure(b) // falseisAVoIDParamClosure(c) // trueisAVoIDParamClosure(d) // falsecallifVoIDVoIDClosure(a) // Prints "Foobar"callifVoIDVoIDClosure(b)callifVoIDVoIDClosure(c)callifVoIDVoIDClosure(d)printTwoTimesResultOfVoIDDoubleClosure(a)printTwoTimesResultOfVoIDDoubleClosure(b) // Prints "42.0"printTwoTimesResultOfVoIDDoubleClosure(c)printTwoTimesResultOfVoIDDoubleClosure(d)== "()" }.contains(false)) { if let foo = foo as? () -> () { foo() } }}func isASingleDoubleReturnTypeClosure<T>(foo: T) -> Bool { let bar = String(foo.dynamicType).componentsSeparatedByString(" -> ") return bar.count > 1 && bar[1] == "Double" /* rhs of '&&' lazily evaluated: [1] ok */}func printTwoTimesResultOfVoIDDoubleClosure<T>(foo: T) { if isAVoIDParamClosure(foo) && isASingleDoubleReturnTypeClosure(foo) { if let foo = foo as? () -> Double { let a: Double = 2*foo() print(a) } }}
当然,正如marcus Rossel在上面的评论中指出的那样,你仍然不会知道关于可调用的参数的任何信息(但也许这可能是下一步找出,因为你知道它是可调用的).
关于OPs问题的补充如下:仅仅是技术讨论,而不是推荐的技术.
您使用与上面相同的方法来检查函数参数是否是没有参数的闭包(() – >(…))或者既没有参数又没有返回类型(() – >()),所以上.使用这种方法,您可以定义一个泛型函数,只有当它具有某种闭包类型时才调用发送给函数的参数.对于这种“函数内调用”,您必须使用类型转换为预期的闭包类型,就像您在上面的Q中所描述的那样.这可能很难绕过这种“非通用”方法w.r.t.调用闭包.下面是一些例子.
示例调用:
总结以上是内存溢出为你收集整理的检查变量是否是Swift中的块/函数/可调用全部内容,希望文章能够帮你解决检查变量是否是Swift中的块/函数/可调用所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)