Mic*_*ord 15 syntax closures ios swift
为了使我的代码更容易阅读,我在Swift中使用类型别名用于各种类型的闭包.我有以下基本的闭包:
public typealias FailureClosure = (error: NSError?) -> Void
public typealias ProgressClosure = (progress: Float32) -> Void
public typealias BasicClosure = () -> Void
Run Code Online (Sandbox Code Playgroud)
我想添加一个typealias支持通用数组的闭包,但我似乎无法弄清楚它的语法.这是我能够得到的,但我得到编译时错误" 使用未声明的类型'T' "
public typealias ArrayClosure = <T>(array:[T]?) -> Void
Run Code Online (Sandbox Code Playgroud)
有人知道怎么做这个吗?或者即使有可能吗?
Rob*_*ier 11
不,这目前不可行.如果它是可能的,你所期望的语法为:
public typealias ArrayClosure<T> = (array:[T]?) -> Void
Run Code Online (Sandbox Code Playgroud)
然后你会喜欢它ArrayClosure<Int>.但它目前不合法.
也就是说,我不推荐这些类型的别名.它们模糊不清,而不是照亮它们.比较这个签名:
func foo(onError: FailureClosure)
Run Code Online (Sandbox Code Playgroud)
有:
func foo(onError: NSError? -> Void)
Run Code Online (Sandbox Code Playgroud)
要保存几个字符,可以强制调用者猜测FailureClosure传递的内容.该error或progress标签不真正帮助你(你还需要使用progress in ...).
一个很有意义的案例就在附近progress,但我认为你想要的类型是:
public typealias Progress = Float32
Run Code Online (Sandbox Code Playgroud)
这里不要误解我,在创建新类型时输入别名会非常有用.Progress是一种碰巧实现为float的类型.但是你正在做的很多事情(绝对与ArrayClosure其他人一起使用,并且在较小程度上与其他人一起)只是在不创建新类型的情况下创建新语法,而这通常会让人感到困惑而不是有用.
要调用您的特定示例,以及为什么过度使用类型别名会导致您使设计过于复杂:
func foo(failure: ((error: NSError?) -> ())? = nil)
Run Code Online (Sandbox Code Playgroud)
你是对的,这真的很复杂.相比:
func foo(failure: NSError -> Void = {_ in return})
Run Code Online (Sandbox Code Playgroud)
这里有两大变化.没有理由有一个带有可选错误的故障块.总是传递错误(如果没有错误,为什么会failure被调用?).并且没有理由将故障块作为可选项.如果您确实需要默认值,只需使默认值不执行任何操作.两个选项消失了,所有消费和实现代码变得更简单.始终要仔细考虑是否绝对必须是可选的.可选项增加了很多复杂性; 不要轻易添加它们.
就个人而言,我可能会在很多情况下使用重载执行此操作:
func foo(#failure: NSError -> Void) { ... }
func foo() {
foo(failure:{ _ in return })
}
Run Code Online (Sandbox Code Playgroud)
我只是觉得理解发生的事情要容易一些.但无论哪种方式都没问题.
编辑(2014年12月):在写了几个月的Swift之后,我在下面的评论中更加喜欢@David的方法,即使用一个可选的闭包,但不是错误.特别是给定Swift的可选链接语法(failure?()),它通常会更清晰.
func foo(failure: (NSError -> Void)? = nil)
Run Code Online (Sandbox Code Playgroud)