Put multiple UILabels into an array - ios

In my app I currently have 9 labels on my storyboard, each showing a different value. (The values are stored in an array). As far as I know, each label has to be connected from the storyboard to the viewcontroller file separately, which makes my code look like this:
#IBOutlet weak var xValue: UILabel!
#IBOutlet weak var yValue: UILabel!
#IBOutlet weak var zValue: UILabel!
#IBOutlet weak var maxXValue: UILabel!
#IBOutlet weak var maxYValue: UILabel!
#IBOutlet weak var maxZValue: UILabel!
#IBOutlet weak var minXValue: UILabel!
#IBOutlet weak var minYValue: UILabel!
#IBOutlet weak var minZValue: UILabel!
And to set the values, I need to manually do:
xValue.text = arr[0]
yValue.text = arr[1]
...
minYValue = arr[7]
minZValue = arr[8]
Is there a way to connect multiple labels from the storyboard into an array so that I can simply do something like:
for i in 0...8 {
labelArray[i] = arr[i]
}

As rmaddy mentioned in a comment you can use an outlet collection:
#IBOutlet private var labels: [UILabel]!
Then in your storyboard labels will show up under Outlet Collections when right-clicking your ViewController, and you can link multiple labels:

You can put all the UILabel into an array, like this:
let labelArray = [xValue, yValue, zValue]
for i in 0..<labelArray.count-1{
labelArray[i] = arr[i]
}

Related

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

These are my Outlets, how can I out all off these in an array?
#IBOutlet weak var progressBar1: UIProgressView!
#IBOutlet weak var progressBar2: UIProgressView!
#IBOutlet weak var progressBar3: UIProgressView!
#IBOutlet weak var progressBar4: UIProgressView!
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
On top declare a variable first like this
var outlets: [UIProgressView] = []
and now on ViewDidLoad method you can use this to put all outlets on that array
like this:
outlets = [progressBar1, progressBar2, progressBar3, progressBar4]
Hope you understand.
class ViewController: UIViewController {
#IBOutlet weak var p1: UIProgressView!
#IBOutlet weak var p2: UIProgressView!
#IBOutlet weak var p3: UIProgressView!
#IBOutlet weak var p4: UIProgressView!
var outlets: [UIProgressView] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
outlets = [
p1,p2,p3,p4
]
}
}
If you have other types of views you can use
var outlets: [UIView] = [...]
As mentioned here Swift - IBOutletCollection equivalent you can use IBOutletCollection to do that. You can drag all your views to one IBOutlet array.
#IBOutlet weak var progressBars: [UIProgressView]!
For example, you can access the first progressBar like
progressBars[0]
But you have to careful about the order of progressBars, when you define IBOutletCollections the collection will not be order guaranteed. You can define the for each view and sort by their tags in runtime as mentioned here also Is IBOutletCollection guaranteed to be of correct order?
To order all views by their tags like
progressBars = progressBars.sorted { $0.tag < $1.tag }

Clean up code? (Xcode freezes at indexing)

I believe I have to clean up my code a bit, since Xcode for the first time started to freeze at "indexing" and I can't run my project. I think it's easy to do, but I don't know what way is the best. Got 36 UIImageViews...
#IBOutlet var Image1: UIImageView!
#IBOutlet var Image2: UIImageView!
#IBOutlet var Image3: UIImageView!
#IBOutlet var Image4: UIImageView!
#IBOutlet var Image5: UIImageView!
#IBOutlet var Image6: UIImageView!
#IBOutlet var Image7: UIImageView!
#IBOutlet var Image8: UIImageView!
#IBOutlet var Image9: UIImageView!
#IBOutlet var Image10: UIImageView!
#IBOutlet var Image11: UIImageView!
#IBOutlet var Image12: UIImageView!
#IBOutlet var Image13: UIImageView!
#IBOutlet var Image14: UIImageView!
#IBOutlet var Image15: UIImageView!
#IBOutlet var Image16: UIImageView!
#IBOutlet var Image17: UIImageView!
#IBOutlet var Image18: UIImageView!
#IBOutlet var Image19: UIImageView!
#IBOutlet var Image20: UIImageView!
#IBOutlet var Image21: UIImageView!
#IBOutlet var Image22: UIImageView!
#IBOutlet var Image23: UIImageView!
#IBOutlet var Image24: UIImageView!
#IBOutlet var Image25: UIImageView!
#IBOutlet var Image26: UIImageView!
#IBOutlet var Image27: UIImageView!
#IBOutlet var Image28: UIImageView!
#IBOutlet var Image29: UIImageView!
#IBOutlet var Image30: UIImageView!
#IBOutlet var Image31: UIImageView!
#IBOutlet var Image32: UIImageView!
#IBOutlet var Image33: UIImageView!
#IBOutlet var Image34: UIImageView!
#IBOutlet var Image35: UIImageView!
#IBOutlet var Image36: UIImageView!
override func viewDidLoad() {
let images = (1...6).map { UIImage(named: "Owl\($0)") }
let imageViewsArray = [Image1, Image2, Image3, Image4, Image5, Image6, Image7, Image8, Image9, Image10, Image11, Image12, Image13, Image14, Image15, Image16, Image17, Image18, Image19, Image20, Image21, Image22, Image23, Image24, Image25, Image26, Image27, Image28, Image29, Image30, Image31, Image32, Image33, Image34, Image35, Image36]
for view in imageViewsArray {
let randomIndex = Int(arc4random_uniform(UInt32(images.count)))
view.image = images[randomIndex]
}
}
Could I make an IBOutlet for all 36 images together? Or something like this? :-)
Info about the code in ViewDidLoad() here.
As #FruitAddict said, an UICollectionView may be useful, depending of what you want to display of course. But if it doesn't fit your needs, you can still use an Outlet connection instead of an outlet :
Thus you can access every labels directly from labelCollection, which is an explicit unwrapped array of UILabel.
Also, in the gif, the second label is added to the collection outlet by draging it to the already existing outlet. The outlet is not replaced (as in a regular object), but instead the new label is added to the array.
EDIT :
As #nhgrif pointed out, don't rely on the order of the objects within the outlet collection :
It's important to note that while many times the order within the outlet collection may coincidentally coincide with the order you dragged them in, Apple makes no guarantees about this and the order within the collection should not be relied upon.
You should consider this array as a set.

Give buttons same behavior (twins)

I would like my UIButtons to interact with each other - (With the corresponding button)
First set of buttons;
#IBOutlet var P1button1: UIButton!
#IBOutlet var P1button2: UIButton!
#IBOutlet var P1button3: UIButton!
#IBOutlet var P1button4: UIButton!
#IBOutlet var P1button5: UIButton!
#IBOutlet var P1button6: UIButton!
#IBOutlet var P1button7: UIButton!
#IBOutlet var P1button8: UIButton!
#IBOutlet var P1button9: UIButton!
Second set of buttons;
#IBOutlet var P2button1: UIButton!
#IBOutlet var P2button2: UIButton!
#IBOutlet var P2button3: UIButton!
#IBOutlet var P2button4: UIButton!
#IBOutlet var P2button5: UIButton!
#IBOutlet var P2button6: UIButton!
#IBOutlet var P2button7: UIButton!
#IBOutlet var P2button8: UIButton!
#IBOutlet var P2button9: UIButton!
In my code I apply an Image to one random P1button from an Array;
var buttons = [P1button1, P1button2, P1button3, P1button4, P1button5, P1button6, P1button7, P1button8, P1button9]
buttons.shuffleInPlace()
buttons[0].setImage(UIImage(named: "Green"), forState: .Normal)
Now, I want to know if there is a way to make the P2buttons "co-operate" with the P1buttons. Meaning that if an Image is applied to P1button1 then P2button1 is set to the same image! (and so forth for all buttons)
Example;
P2button1.setImage = UIImage(P1button1)
This obviously doesn't work but hopefully gives you a clue about what I'm trying to achieve.
One possible approach would be by subclassing UIButton. Perhaps something like this...
class TwinButton {
weak var twin: TwinButton?
}
Now, in your viewDidLoad method, link up all of the twins.
p1button1.twin = p2button1
p2button1.twin = p1button1
Now, I'd write a set of methods that have some "with twin" semantics...
extension TwinButton {
setWithTwin(title: String)
setWithTwin(backgroundImage: UIImage)
}
and those methods simply set the value on self and twin.

Array of Outlets of type Label

I have 16 Outlets variables.
#IBOutlet var label00: UILabel?
#IBOutlet var label01: UILabel?
#IBOutlet var label02: UILabel?
#IBOutlet var label03: UILabel?
#IBOutlet var label10: UILabel?
#IBOutlet var label11: UILabel?
#IBOutlet var label12: UILabel?
#IBOutlet var label13: UILabel?
#IBOutlet var label20: UILabel?
#IBOutlet var label21: UILabel?
#IBOutlet var label22: UILabel?
#IBOutlet var label23: UILabel?
#IBOutlet var label30: UILabel?
#IBOutlet var label31: UILabel?
#IBOutlet var label32: UILabel?
#IBOutlet var label33: UILabel?
I want to declare them as an array but don't know how to do it.
You have to create IBOutlet Collection like as
#IBOutlet var labels: Array<UILabel>!
For more reference of code check this question :
1) Can't hook up an outlet collection in Xcode 6 using storyboard
2) Swift - IBOutletCollection equivalent
For example :
Follow these steps to create an array of outlets an connect it with IB Elements:
Create an array of IBOutlets
Add multiple UIElements (Views) in your Storyboard ViewController interface
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()
}
}

Collection of Collection of UIViews

In my Swift app I have 9 outlets:
#IBOutlet weak var day1: UIImageView!
#IBOutlet weak var day1Title: UILabel!
#IBOutlet weak var day1Description: UILabel!
#IBOutlet weak var day2: UIImageView!
#IBOutlet weak var day2Title: UILabel!
#IBOutlet weak var day2Description: UILabel!
#IBOutlet weak var day3: UIImageView!
#IBOutlet weak var day3Title: UILabel!
#IBOutlet weak var day3Description: UILabel!
I'd like to "group" these together by their day using an integer as the key. So 1 maps to day1, day1Title, day1Description.
So that I could assign label text to each of the above generically rather than have to reference the specific image view, label, and description.
Any thoughts/suggestions?
I thought maybe:
Dictionary<int, Array<UIImageView, UILabel, UILabel>>
or
Dictionary<int, Array<UIView>>
but i'm not quite sure about this being the right move. Could I somehow assign a class that has 3 properties that reference these outlets maybe?
Or perhaps 3 outlet collections?
What do you think is good to do?
Thanks!
Why use a dictionary with an integer key? An array of 9 elements should work just as well. In addition, the value would be better represented as a tuple instead of as an array.
Array<(UIImageView, UILabel, UILabel)>
or
[(UIImageView, UILabel, UILabel)]
result
var views: [(UIImageView, UILabel, UILabel)]
…
views = [(day1, day1Title, day1Description),
(day2, day2Title, day2Description),
…
(day9, day9Title, day9Description)]
…
var (imageView, titleLabel, descriptionLabel) = views[dayNumber - 1]

Resources