Is Iboutletcollection Guaranteed to Be of Correct Order

Is IBOutletCollection guaranteed to be of correct order?

Both sources are sort of right: on one hand, due to the implementation details of the Interface Builder, the order in which you add items to IBOutletCollection will be maintained on retrieval; on the other hand, you should avoid making use of that ordering in your code, because there is no way to check this order.

Imagine taking over someone else's project. If you see a loop over an IBOutletCollection, observe that the order of iteration matters, and decide to check what that order is or force the new order, you would have to remove and re-add the controls to your outlet collection. That is why you should treat your IBOutletCollection elements as unordered. If it is necessary to maintain a specific order, copy the elements into an NSArray, sort them on some known property, and then iterate the copied collection.

IBOutletCollection - how is ordering applied to the array?

You cannot use IBOutletCollection safely without adding an additional property like the tag if the ordering is important.

Sometimes they will retain the order in where the connections were added but sometimes they wont.

There are other similar questions that talk about this:

IBOutletCollection set ordering in Interface Builder

IBOutletCollection set ordering in Interface Builder

EDIT: Several commenters have claimed that more recent versions of Xcode return IBOutletCollections in the order the connections are made. Others have claimed that this approach didn't work for them in storyboards. I haven't tested this myself, but if you're willing to rely on undocumented behavior, then you may find that the explicit sorting I've proposed below is no longer necessary.


Unfortunately there doesn't seem to be any way to control the order of an IBOutletCollection in IB, so you'll need to sort the array after it's been loaded based on some property of the views. You could sort the views based on their tag property, but manually setting tags in IB can be rather tedious.

Fortunately we tend to lay out our views in the order we want to access them, so it's often sufficient to sort the array based on x or y position like this:

- (void)viewDidLoad
{
[super viewDidLoad];

// Order the labels based on their y position
self.labelsArray = [self.labelsArray sortedArrayUsingComparator:^NSComparisonResult(UILabel *label1, UILabel *label2) {
CGFloat label1Top = CGRectGetMinY(label1.frame);
CGFloat label2Top = CGRectGetMinY(label2.frame);

return [@(label1Top) compare:@(label2Top)];
}];
}

How can I add make an array for all of my IBOutlets?

Open the Assistant Editor, right-click and drag from one of your UIProgressView's or just drag from its "Referencing Outlet Collections" to the code file.
Insert outlet collection

Then you can drag from your swift file's @IBOutlet to the rest of your UIProgressView's. Add view to collection

Selecting and deselecting collection of buttons

You can simply create collection of UIButton. After that assign tag of all three UIButton from Storyboard.

@IBOutlet var buttons: [UIButton]!

Use above collection and connect all the button with Outlet. also connect below action with all buttons.

@IBAction func buttonPressed(_ sender: UIButton) {
buttons.forEach { $0.isSelected = false
$0.setTitleColor(.white, for: .normal)
}

buttons[sender.tag].setTitleColor(.red, for: .normal)
buttons[sender.tag].isSelected = true
}

Indexes or tags? For multiple checkboxes as buttons in IBOutletCollection

On storyboard you can set tag for every button in attribute inspector. In image you can see the selected button and tag property for it in Attributes inspector Following is the altered code:

@IBAction func boxTouched(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
let buttonTag = sender.tag
switch tag {

case 0:
//code you want to write for case 0
case 1:
//code you want to write for case 1
case 2:
//code you want to write for case 2
case 3:
//code you want to write for case 3
case 4:
//code you want to write for case 4
default:
//code you want to write for default case

}

}

Select a Specific UIButton with numbers

I suggest assigning sequential tags to your buttons starting at some fixed offset, then using viewWithTag, to fetch the buttons as suggested in DanielM's alternative suggestion.

#define K_TAG_BASE 100   //BUTTON TAGS START AT 100

int tag = arc4random() % 35 + K_TAG_BASE;

NSButton aButton = [self.view viewWithTag: tag];
aButton.layer.borderColor = [[UIColor darkGrayColor] CGColor];

Referencing an array of IBOutlet 's (NSButton)

This is probably a good example of using an NSMatrix object.

You can add one button to your interface and then with the button selected in Xcode 4 go to Editor > Embed In > Matrix. Then you can option drag on a corner of the button to expand it into a matrix.

NSMatrix allows you to retrieve the cell values by searching for a given tag or by column/row coordinates.

HOW TO:
1) Embedding the NSButton object:

Creating a button matrix

2) Option-Drag any of the button corners to expand the matrix:

Sample Image

Multiple Choice Quiz: Need to set title of each button to each question multiple choice answer

You set first index of answerChoices array for all options with AnswerQuestions initially = 0 , instead you need

optionA.setTitle(surveyQuestions?.questions[questionNumbers].answerChoices[0].text, for: .normal)
optionB.setTitle(surveyQuestions?.questions[questionNumbers].answerChoices[1].text, for: .normal)
optionC.setTitle(surveyQuestions?.questions[questionNumbers].answerChoices[2].text, for: .normal)
optionD.setTitle(surveyQuestions?.questions[questionNumbers].answerChoices[3].text, for: .normal)
optionE.setTitle(surveyQuestions?.questions[questionNumbers].answerChoices[4].text, for: .normal)

It'll be easier if you have created an IBOutlet collection

@IBOutlet var allOptions: [UIButton]!

and hooked all buttons to it , in this case you can do

allOptions.indices.forEach { allOptions[$0].setTitle(surveyQuestions?.questions[questionNumbers].answerChoices[$0].text, for:.normal)  }


Related Topics



Leave a reply



Submit