Swift 选择器和闭包讨论
Swift Selectors and Closures Discussion
我搜索了很多,但没有找到任何真正有助于解决我的问题的东西...
我正在尝试从头开始构建一个简单的 UIControl,例如 UIButton。由于特殊原因,它不能是 UIControl 的子类。
我需要这个控件来做这样的事情:
myControl.addTarget(target: AnyObject?, action: Selector, forControlEvents: UIControlEvents)
问题是触摸按钮时执行此选择器的方法的实现需要"performSelector:"方法。
Swift 没有 "performSelector:"。所以我教它可以使用闭包来实现。
我不知道如何在闭包中捕获我想修改的对象。
而且我不确定我将如何处理参考循环和其他类似的事情。
我什至不知道我是否在正确的道路上取得成功。我相信你们可以让我走上正轨!
我来自巴西,抱歉我的英语不好!谢谢! :D
这是到目前为止的内容...
struct ClosureForEvent {
var closure:(control:MyControl!)->()
var event:UIControlEvents
}
class MyControl {
private var closures:[ClosureForEvent]?
init() {}
func addClosureFor(event:UIControlEvents, closure:(control:MyControl!)->()) {
if closures == nil {
closures = [ClosureForEvent(closure: closure, event: event)]
}
else {
closures!.append(ClosureForEvent(closure: closure, event: event))
}
}
func executeClosuresOf(event:UIControlEvents) {
if closures != nil {
for closure in closures! {
if closure.event == event {
closure.closure(control: control)
}
}
}
}
}
class Test {
var testProperty = "Default String"
init() {
let control = MyControl()
control.addClosureFor(UIControlEvents.TouchUpInside, closure: { (control) -> () in
self.testProperty = "This is making a reference cycle?"
})
}
}
目前您的情况似乎没有形成循环引用。但有可能在未来不小心形成。喜欢下面的例子。
// In the `Test` class.
let control = MyControl()
init() {
control.addClosureFor(UIControlEvents.TouchUpInside, closure: { (control) -> () in
self.testProperty = "This is making a reference cycle?"
})
}
在此代码中,self
引用了 control
作为其字段,而 control
通过 [= 添加的闭包引用了 self
16=]。这形成了一个循环引用,因此循环中的这些对象永远不会被释放。
闭包捕获列表有助于解决这个问题。
control.addClosureFor(UIControlEvents.TouchUpInside) { [weak self] /* <-- */ control -> () in
// Here, `self` is visible as `Optional<Test>` so the `?` operator is required.
self?.testProperty = "This is making a reference cycle?"
return
}
在上面的代码块中,self
被弱捕获,因此从self
到control
形成了唯一一个单向引用。
请注意,现在在闭包中,无法保证对 self
的访问,因为 self
是弱引用的。您必须考虑 self
一个可选值。
我搜索了很多,但没有找到任何真正有助于解决我的问题的东西...
我正在尝试从头开始构建一个简单的 UIControl,例如 UIButton。由于特殊原因,它不能是 UIControl 的子类。
我需要这个控件来做这样的事情:
myControl.addTarget(target: AnyObject?, action: Selector, forControlEvents: UIControlEvents)
问题是触摸按钮时执行此选择器的方法的实现需要"performSelector:"方法。
Swift 没有 "performSelector:"。所以我教它可以使用闭包来实现。
我不知道如何在闭包中捕获我想修改的对象。 而且我不确定我将如何处理参考循环和其他类似的事情。
我什至不知道我是否在正确的道路上取得成功。我相信你们可以让我走上正轨!
我来自巴西,抱歉我的英语不好!谢谢! :D
这是到目前为止的内容...
struct ClosureForEvent {
var closure:(control:MyControl!)->()
var event:UIControlEvents
}
class MyControl {
private var closures:[ClosureForEvent]?
init() {}
func addClosureFor(event:UIControlEvents, closure:(control:MyControl!)->()) {
if closures == nil {
closures = [ClosureForEvent(closure: closure, event: event)]
}
else {
closures!.append(ClosureForEvent(closure: closure, event: event))
}
}
func executeClosuresOf(event:UIControlEvents) {
if closures != nil {
for closure in closures! {
if closure.event == event {
closure.closure(control: control)
}
}
}
}
}
class Test {
var testProperty = "Default String"
init() {
let control = MyControl()
control.addClosureFor(UIControlEvents.TouchUpInside, closure: { (control) -> () in
self.testProperty = "This is making a reference cycle?"
})
}
}
目前您的情况似乎没有形成循环引用。但有可能在未来不小心形成。喜欢下面的例子。
// In the `Test` class.
let control = MyControl()
init() {
control.addClosureFor(UIControlEvents.TouchUpInside, closure: { (control) -> () in
self.testProperty = "This is making a reference cycle?"
})
}
在此代码中,self
引用了 control
作为其字段,而 control
通过 [= 添加的闭包引用了 self
16=]。这形成了一个循环引用,因此循环中的这些对象永远不会被释放。
闭包捕获列表有助于解决这个问题。
control.addClosureFor(UIControlEvents.TouchUpInside) { [weak self] /* <-- */ control -> () in
// Here, `self` is visible as `Optional<Test>` so the `?` operator is required.
self?.testProperty = "This is making a reference cycle?"
return
}
在上面的代码块中,self
被弱捕获,因此从self
到control
形成了唯一一个单向引用。
请注意,现在在闭包中,无法保证对 self
的访问,因为 self
是弱引用的。您必须考虑 self
一个可选值。