Swift - IBOutletCollection的等效方式

57

我正在尝试用Swift复制“Developing ios7 apps for iphone and ipad”在iTunesU中的Stanford Matchismo游戏。

在第三节课程的第77页幻灯片中,它展示了使用IBOutletCollection,但是这在Swift中不是一个选项。Swift文档示例展示了一个包含IBOutlet数组的例子,但我不知道如何让Interface Builder将多个输出连接到同一个IBOutlet/IBOutlet数组。

是否有人已经想出如何做到这一点了?

我知道我可以创建12个outlet并处理它,但我想让它尽可能地接近课堂演示中的示例。


1
Xcode没有像对待@IBOutlet@IBAction一样对待@IBOutletCollection进行语法高亮,而且在苹果文档页面中也没有提到。看起来这个功能可能还没有出现或者不会出现了。 - Nate Cook
1
已提交错误报告:17200892。 - Alcanzar
@Alcanzar 有关那个 bug 的最新进展吗? - Andrew
我的问题被标记为“15607242(打开)的重复”,所以肯定是一个真正的问题。 - Alcanzar
对于任何正在跟踪的人来说,Xcode beta2中仍未修复此问题。 - Alcanzar
7个回答

89

更新:现在在Xcode中可以正常工作 - "Outlet Collection"是Interface Builder中的连接选项之一,它创建了一个类似于以下内容的东西:

@IBOutlet var labelCollection: [UILabel]!

当我们在等待修复时,您可以使用计算属性来近似实现此功能。假设我的视图有五个UILabels需要放在一个集合中,我仍然需要声明每个标签,但同时也声明一个计算属性来收集它们:

class MyViewController {
    @IBOutlet var label1 : UILabel
    @IBOutlet var label2 : UILabel
    @IBOutlet var label3 : UILabel
    @IBOutlet var label4 : UILabel
    @IBOutlet var label5 : UILabel
    var labels: UILabel![] { return [label1, label2, label3, label4, label5] }

有点烦人,但从那时起,我们可以将labels属性视为一个IBOutletCollection,并且一旦修复了该错误,就不必更改其余的代码:

override func viewDidLoad() {
    super.viewDidLoad()

    for (index, item) in enumerate(self.labels) {
        item.text = "Label #\(index)"
    }
}

3
乍一看似乎是有效的,但实际上并不是。它比我之前尝试使用的 UILabel[] 更好,因为我可以从 IBOutlet 拖动到特定的按钮,但如果我尝试添加第二个按钮,它会替换第一个按钮。此外,如果我只将其连接到一个按钮并尝试运行,Swift 将无法启动(命令/Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift 失败,退出码为254)。 - Alcanzar
哦,天啊。这意味着Matchismo项目有30行只是变量定义...我猜这就是当你试图在一个公开不到一个月的语言中编码时会得到的结果。 - danielbh
这就是为什么他们称之为“前沿技术”。 - Nate Cook
至少,这个可以暂时解决,希望很快会有一些真正的IBOutletCollection。 - Sruit A.Suk
可以用。谢谢 - 好的提示! - nspire
显示剩余2条评论

27

使用:

@IBOutlet var lineFields: [UITextField]!

然后,依次从UITextField元素向lineFields进行控制拖动。


16
@IBOutlet var buttons : [UIView]!

然后从连接检查器中拖动它到界面构建器中,或者您通常用于此操作的任何方法


10

编辑

这个问题在Swift的后期Beta版本中得到了修复 - 现在在接口构建器中有一个IBCollection选项。


对于较早的Swift Beta版本:

我遇到了同样的问题:在Beta 2的发布说明中,您会发现以下声明:

Interface Builder不支持在Swift类中声明outlet集合

我通过以下方式解决了这个问题(易于定制):

class CardGameViewController: UIViewController {
  @lazy var cardButtons : UIButton[] = {
    var tempBtn: UIButton[] = []
    for v:AnyObject in self.view.subviews {
      if v is UIButton {
        tempBtn.append(v as UIButton)
      }
    }
    return tempBtn
  }()
...

基本上,它循环遍历所有子视图并检查是否有一个UIButton。在这种情况下,它会被添加到临时数组中。然后使用此临时数组来延迟实例化cardButtons数组。有关所有详细信息,请检查:Matchismo:Objective-C转Swift


9

按照以下步骤创建一个出口的数组,并将其与IB元素连接:

  • 创建一个IBOutlets的数组
  • 在你的Storyboard ViewController界面中添加多个UIElements(视图)(如下图所示)
  • 选择ViewController(在Storyboard中),打开连接检查器
  • 连接检查器中有“Outlet Collections”选项(您将在那里看到一组出口)
  • 将其与您的界面元素连接起来

-

class ViewController2: UIViewController {


    @IBOutlet var collection:[UIView]!


    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

enter image description here


2

1

根据@machine所说,这似乎是当前状态(XCode 7.1)与iOS 9绑定的情况。关键是按顺序将它们全部拖动。使用第一个项目控制+拖动到控制器代码中,然后将Outlet类型更改为collection。之后从控制器代码文件中拖动出口点,依次拖动到每个屏幕控件上(如@machine所说)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接