通过直接引用或关闭

时间:2015-01-10 20:24:41

标签: swift closures

来自不同的语言背景,将方法传递给另一个对象的方式不同,如下所示(方法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)
    }
}

2 个答案:

答案 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会警告你(如果您知道捕获不是问题,例如在调用selfmap时引用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 inself.callback(message)之间插入其他语句。如果没有这些额外的陈述(如你的逐字例子),我倾向于采用方法A.