Swift - IBOutletCollection equivalent

SwiftInterface BuilderIboutletIboutletcollection

Swift Problem Overview


I'm trying to replicate the Stanford Matchismo game from "Developing ios7 apps for iphone and ipad" in iTunesU in Swift.

On page 77 of the 3rd lecture slides, it shows using an IBOutletCollection which isn't an option on Swift. The Swift doc example shows one example that has an array of IBOutlet, but I can't figure out how to make Interface Builder connect multiple outlets to the same IBOutlet/IBOutlet Array.

Has anyone figured out how to do this yet?

I know that I can create 12 outlets and deal with it that way, but I'd like to make this work as closely as possible to the example in the lecture slides.

Swift Solutions


Solution 1 - Swift

Update: This works properly in Xcode now - "Outlet Collection" is one of the connection options in Interface Builder, which creates something that looks like:

@IBOutlet var labelCollection: [UILabel]!

While we're waiting for a fix, you can approximate this using a computed property. Let's say my view has five UILabels that I want in a collection. I still have to declare each one, but then I also declare a computed property that collects them:

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] }

Kind of annoying, but from then on we can treat the labels property as if it were an IBOutletCollection, and won't have to change the rest of our code once the bug is fixed:

override func viewDidLoad() {
    super.viewDidLoad()

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

Solution 2 - Swift

Use:

@IBOutlet var lineFields: [UITextField]!

Then control-drag from UITextField elements to lineFields in order.

Solution 3 - Swift

@IBOutlet var buttons : [UIView]!

then drag it from the connections inspector in the interface builder or whatever metod you usually use for that

Solution 4 - Swift

EDIT

> This was fixed in a later Beta release of Swift - there's now in > IBCollection option in the interface builder.


For early Beta releases of Swift:

I came across the same problem: in the release notes of Beta 2 you find the following statement: > Interface Builder does not support declaring outlet collections in Swift classes

I solved this the following way (easy to customize):

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
  }()
...

Basically, it loops through all the subviews and checks if one is a UIButton. In that case it gets added to a temporary array. This temporary array is then used to lazy instantiate the cardButtons array. For all details, check: Matchismo: Objective-C to Swift

Solution 5 - Swift

Follow steps to create an array of outlets and connect it with IB Elements:

  • Create an array of IBOutlets

  • Add multiple UIElements (Views) in your Storyboard ViewController interface (As shown in below snapshot)

  • Select ViewController (In storyboard) and open connection inspector

  • There is option 'Outlet Collections' in connection inspector (You will see an array of outlets there)

  • Connect if with your interface elements

class ViewController2: UIViewController {
    @IBOutlet var collection:[UIView]!
    

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

enter image description here

Solution 6 - Swift

I got this working in Xcode seed 3 using this syntax

@IBOutlet strong var views: NSArray?

See my discussion here: https://stackoverflow.com/a/24686602/341994

Solution 7 - Swift

What @machine said seems to be the current state (XCode 7.1) with iOS 9 bindings. The key is to drag them all in order. Use the first item to control+drag into the controller code and then change the Outlet type to collection. After the from the controller code file drag the outlet point onto each of the screen controls one by one in order (as @machine says)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlcanzarView Question on Stackoverflow
Solution 1 - SwiftNate CookView Answer on Stackoverflow
Solution 2 - SwiftmachineView Answer on Stackoverflow
Solution 3 - SwiftZiggySTView Answer on Stackoverflow
Solution 4 - SwiftapotryView Answer on Stackoverflow
Solution 5 - SwiftKrunalView Answer on Stackoverflow
Solution 6 - SwiftmattView Answer on Stackoverflow
Solution 7 - SwiftKramsView Answer on Stackoverflow