Collection of Collection of UIViews - ios

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]

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 }

Put multiple UILabels into an array

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

Swift 3: Defining var labels: [UILabel] fails [duplicate]

This question already has answers here:
How to initialize properties that depend on each other
(4 answers)
Closed 6 years ago.
I'm stuck at a variable declaration in Swift 3. My code looks like this:
Beginning of code
// Letter Buttons
#IBOutlet weak var LetterOneButton: UIButton!
#IBOutlet weak var LetterTwoButton: UIButton!
#IBOutlet weak var LetterThreeButton: UIButton!
#IBOutlet weak var LetterFourButton: UIButton!
#IBOutlet weak var LetterFiveButton: UIButton!
// Word Fields
#IBOutlet weak var WordLetterOne: UILabel!
#IBOutlet weak var WordLetterTwo: UILabel!
#IBOutlet weak var WordLetterThree: UILabel!
#IBOutlet weak var WordLetterFour: UILabel!
#IBOutlet weak var WordLetterFive: UILabel!
// Counter
#IBOutlet weak var CounterLabel: UILabel!
// Skip Button
#IBOutlet weak var SkipButtonLabel: UIButton!
// Define Variables
var index: Int = 0
The error appears in the following line:
var labels: [UILabel] = [WordLetterOne, WordLetterTwo, WordLetterThree, WordLetterFour, WordLetterFive]
Error message is "Cannot use instance member 'WordLetterOne' within property initializer; property initializers run before 'self' is available". Afterwards, another string is declared without any problems.
var letters: [String] = ["A", "B", "C", "D", "E"]
End of code
And help is highly appreciated!
Edit:
self.lazy var labels: [UILabel] = [WordLetterOne, WordLetterTwo, WordLetterThree, WordLetterFour, WordLetterFive]
is giving the errors "Consecutive declarations on a line must be separated by ';'" and "Instance member 'WordLetterOne' cannot be used on type 'ViewController'"
Like it says: when the runtime builds the array initalizer, the properties you're trying to put in the array are not defined yet (because self is not ready yet).
Try to make the properties static (depends on your actual situation).
Or -- initialize the labels array in the init method.
The definition of letters is ok because "A", "B", etc are constants.

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.

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

Resources