Swift选择器和闭包讨论 [英] Swift Selectors and Closures Discussion

查看:165
本文介绍了Swift选择器和闭包讨论的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我搜索了很多,没有找到任何真正帮助解决我的问题...

I searched a lot and haven't found anything that really helped to solve my problem...

我试图从头构建一个简单的UIControl,像一个UIButton。它不能是UIControl的子类的特殊原因。

I'm trying to build a simple UIControl from scratch, like a UIButton. It can't be subclass of UIControl for particular reasons.

我需要这个控件做这样:

I need this control to do something like this:

myControl.addTarget(target: AnyObject?, action: Selector, forControlEvents: UIControlEvents)

问题是,当触摸按钮时执行此选择器的方法的实现需要performSelector:方法。

The problem is that the implementation of the method that execute this selector when the button is touched needs the "performSelector:" method.

Swift doesn没有performSelector:。所以我教它可以使用闭包实现。

Swift doesn't have a "performSelector:". So I taught it could be implemented using closures.

我不知道如何捕获我想在闭包中修改的对象。
我不知道如何处理参考循环和其他类似的事情。

I couldn't figure out how to capture the objects I want to modify inside the closure. And I'm not sure how I would deal with reference cycles and other things like that.

我甚至不知道我是否在右边路径成功。我相信你们可以把我放在正确的轨道!

I don't even know if I am on the right path to succeed this. I'm sure you guys can put me on the right track!

我来自巴西,对不起我的可怜的英语!谢谢! :D

I'm from Brazil, sorry for my poor English! Thanks! :D

这是到目前为止...

Here is what a have so far...

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 your case at the moment, it seems that no cyclic-reference is formed. But it's possible to accidentally be formed in the future. Like the followings for the instance.

// In the `Test` class.
let control = MyControl()
init() {
    control.addClosureFor(UIControlEvents.TouchUpInside, closure: { (control) -> () in
        self.testProperty = "This is making a reference cycle?"
    })
}

该代码 self 引用控制作为其字段和 code>通过 addClosureFor 添加的闭包引用 self 。这形成一个循环引用,因此循环中的这些对象永远不会被释放。

In this code, self has a reference to the control as its field and the control has a reference to self through the closure added by addClosureFor. This forms a cyclic reference so these objects in the cycle are never released.

关闭捕获列表有助于解决此问题。

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 控制
请注意,现在在闭包中,对 self 的访问不放心,因为 self 是弱参考。您必须考虑 self 一个可选值。

In the block in this code above, self is weakly captured so that an only one unidirectional reference is formed from self to the control. Note that, now in the closure, the access to self isn't assured because self is weakly-referenced. You have to consider self an optional value.

https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ AutomaticReferenceCounting.html

这篇关于Swift选择器和闭包讨论的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆