来自不同的语言背景,将方法传递给另一个对象的方式不同,如下所示(方法A),但我注意到在Objective-C和SWIFT中传递块的样式,&#& 39; SWIFT推荐的方式是什么?为什么? (优点和缺点是什么?)
class Messenger {
private var _method: ((String) -> ())
init(method: (String -> ())) {
_method = method
}
}
class Test {
init() {
Messenger(method: self.callback) //approach A
Messenger({
message in self.callback(message) //approach B - Wrapper/Block style
})
}
func callback(message: String) {
println(message)
}
}
答案 0 :(得分:3)
你的方法A是要走的路。方法B实际上不起作用 - 你声明一个匿名函数,它接受一个参数并且对它没有任何作用,而是将它用作另一个函数callback
的参数。这基本上就像这样说:
func f(arg1: Int) {
// do nothing but call g
g(arg1)
}
f(1) // no different to calling g(1)
takeFunc(f) // no different to passing in g
重要的是要认识到用闭包表达式语法let f: Int->Bool = { i in etc }
声明的函数和用func
关键字func f(i: Int)->Bool { etc }
声明的函数完全相同。有微妙的差异,但不是基本的差异。
重新关注强引用 - 选项B中的闭包表达式并不能真正帮助解决问题。在选项A中,通过传入指向实例的成员函数的指针,将隐式引用传递给self。在选项B中,您声明了一个“捕获”self
的匿名闭包,然后传递它,但是存储的匿名函数将使self
保持活跃,就像存储self.memfun
一样,只是有额外的间接水平。实际上,很容易忘记通过闭包表达式捕获self
可能是一个风险,如果你意外隐式地执行它并强迫你在那里放置一个明确的self
,Swift会警告你(如果您知道捕获不是问题,例如在调用self
或map
时引用filter
时,这可能会非常烦人。
要编写一个不捕获self的回调函数,您必须使用capture list:
Messenger { [weak self] message in // weak or unowned depending on how Messenger is being used
self?.callback(message) // if weak, self needs to be optional
return // return needed since otherwise it will attempt to return ()?
}
顺便说一下,写更多Swift-y Swift的最好方法就是弃掉很多多余的括号:-)
e.g。
// no need to wrap entire function type in (),
// and single argument types (i.e. 1-element tuples)
// don’t need () surrounding them:
private var _method: String -> ()
而不是
private var _method: ((String) -> ())
和
Messenger { // closure exprs can be outside the () of functions
// when they’re the last argument (and () can be
// left out completely when they’re the only argument)
message in self.callback(message)
}
而不是
Messenger({
message in self.callback(message) //approach B - Wrapper/Block style
})
答案 1 :(得分:0)
您的方法B允许您在message in
和self.callback(message)
之间插入其他语句。如果没有这些额外的陈述(如你的逐字例子),我倾向于采用方法A.