Clean up code? (Xcode freezes at indexing) - ios

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.

Related

How to make normal content look scrollable (like a UITableView)

I have a view controller with a few labels and switches inside of it. Is there any way to make the whole view look "scrollable" like how UITableViewCells look. Like even if there isn't enough content to need it to be scrollable I want that interactive gesture that UITableViewCells have. The whole point of this is to make all the pages on my app feel similar. Is there any way to add that same "scrolling" or "dynamic" feeling to the normal view?
Edit: A link to show what I mean
https://imgur.com/a/wJtfIKK
Here is the code where I connect the scroll view and I am making it "scrollable"
class ThemesViewController: UIViewController {
#IBOutlet weak var spacer: UIView!
#IBOutlet weak var overrideThemeDesc: UILabel!
#IBOutlet weak var overrideSystemTheme: UILabel!
#IBOutlet weak var overrideThemeToggle: UISwitch!
#IBOutlet weak var backgroundView: UIView!
#IBOutlet weak var lightButton: RadioButton!
#IBOutlet weak var darkButton: RadioButton!
#IBOutlet weak var lightText: UILabel!
#IBOutlet weak var darkText: UILabel!
#IBOutlet weak var appearanceLabel: UILabel!
#IBOutlet var interactiveView: UIScrollView!
let themeOverrideDefaults = UserDefaults.standard
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
interactiveView.alwaysBounceVertical = true
// Rest of My Code
}
And here is a picture of the storyboard with the scroll view selected (to show it has custom class UIScrollView): https://imgur.com/a/YCKPKpj
You can embed your view into a UIScrollView and then set
scrollView.alwaysBounceVertical = true
so that you get that scrolling effect even if the content is not large enough to be scrolled.
https://developer.apple.com/documentation/uikit/uiscrollview/1619383-alwaysbouncevertical

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

Xcode Swift Calculate average of 23 Text Field values

I am new to iOS programming. I am making an app which reads values of Text Fields and calculates the average value. I have 23 Text Fields. Here is what I have.
import UIKit
class SavedBerekenenViewController: UIViewController {
#IBOutlet weak var naam1: UITextField!
#IBOutlet weak var cijfer1: UITextField!
#IBOutlet weak var weging1: UITextField!
#IBOutlet weak var naam2: UITextField!
#IBOutlet weak var weging2: UITextField!
#IBOutlet weak var cijfer2: UITextField!
#IBOutlet weak var weging3: UITextField!
#IBOutlet weak var cijfer3: UITextField!
#IBOutlet weak var weging4: UITextField!
#IBOutlet weak var cijfer4: UITextField!
#IBOutlet weak var weging5: UITextField!
#IBOutlet weak var cijfer5: UITextField!
#IBOutlet weak var weging6: UITextField!
#IBOutlet weak var cijfer6: UITextField!
#IBOutlet weak var weging7: UITextField!
#IBOutlet weak var cijfer7: UITextField!
#IBOutlet weak var weging8: UITextField!
#IBOutlet weak var cijfer8: UITextField!
#IBOutlet weak var weging9: UITextField!
#IBOutlet weak var cijfer9: UITextField!
#IBOutlet weak var weging10: UITextField!
#IBOutlet weak var cijfer10: UITextField!
#IBOutlet weak var weging11: UITextField!
#IBOutlet weak var cijfer11: UITextField!
#IBOutlet weak var weging12: UITextField!
#IBOutlet weak var cijfer12: UITextField!
#IBOutlet weak var weging13: UITextField!
#IBOutlet weak var cijfer13: UITextField!
#IBOutlet weak var weging14: UITextField!
#IBOutlet weak var cijfer14: UITextField!
#IBOutlet weak var weging15: UITextField!
#IBOutlet weak var cijfer15: UITextField!
#IBOutlet weak var weging16: UITextField!
#IBOutlet weak var cijfer16: UITextField!
#IBOutlet weak var weging17: UITextField!
#IBOutlet weak var cijfer17: UITextField!
#IBOutlet weak var weging18: UITextField!
#IBOutlet weak var cijfer18: UITextField!
#IBOutlet weak var weging19: UITextField!
#IBOutlet weak var cijfer19: UITextField!
#IBOutlet weak var weging20: UITextField!
#IBOutlet weak var cijfer20: UITextField!
#IBOutlet weak var weging21: UITextField!
#IBOutlet weak var cijfer21: UITextField!
#IBOutlet weak var weging22: UITextField!
#IBOutlet weak var cijfer22: UITextField!
#IBOutlet weak var weging23: UITextField!
#IBOutlet weak var cijfer23: UITextField!
#IBOutlet weak var LBgemiddelde: UILabel!
var text: String = ""
var I: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.title = text
}
func gemiddelde() {
let aantalCijfers:Double = (Double(weging1.text!)! + Double(weging2.text!)! + Double(weging3.text!)! + Double(weging4.text!)! + Double(weging5.text!)! + Double(weging6.text!) + Double(weging7.text!)! + Double(weging8.text!)! + Double(weging9.text!)! + Double(weging10.text!)! + Double(weging11.text!)! + Double(weging12.text!)! + Double(weging13.text!)! + Double(weging14.text!)! + Double(weging15.text!)! + Double(weging16.text!)! + Double(weging17.text!)! + Double(weging18.text!)! + Double(weging19.text!)! + Double(weging20.text!)! + Double(weging21.text!)! + Double(weging22.text!)! + Double(weging23.text!)!)
let som:Double = (Double(cijfer1.text!)! * Double(weging1.text!)! + Double(cijfer2.text!)! * Double(weging2.text!) + Double(cijfer3.text!)! * Double(weging3.text!)! + Double(cijfer4.text!)! * Double(weging4.text!)! + Double(cijfer5.text!)! * Double(weging5.text!)! + Double(cijfer6.text!)! * Double(weging6.text!)! + Double(cijfer7.text!)! * Double(weging7.text!)! + Double(cijfer8.text!)! * Double(weging8.text!)! + Double(cijfer9.text!)! * Double(weging9.text!)! + Double(cijfer10.text!)! * Double(weging10.text!)! + Double(cijfer11.text!)! * Double(weging11.text!)! + Double(cijfer12.text!)! * Double(weging12.text!)! + Double(cijfer13.text!)! * Double(weging13.text!)! + Double(cijfer14.text!)! * Double(weging14.text!)! + Double(cijfer15.text!)! * Double(weging15.text!)! + Double(cijfer16.text!)! * Double(weging16.text!)! + Double(cijfer17.text!)! * Double(weging17.text!)! + Double(cijfer18.text!)! * Double(weging18.text!)! + Double(cijfer19.text!)! * Double(weging19.text!)! + Double(cijfer20.text!)! * Double(weging20.text!)! + Double(cijfer21.text!)! * Double(weging21.text!)! + Double(cijfer22.text!)! * Double(weging22.text!)! + Double(cijfer23.text!)! * Double(weging23.text!)!)
let gemiddeldedouble:Double = (som / aantalCijfers)
LBgemiddelde.text = String(gemiddeldedouble)
}
#IBAction func bereken(_ sender: UIButton) {
gemiddelde()
}
I don't think this is the proper way to do this, so please help.
Use IBOutletCollection or it's equivalent as follows:
#IBOutlet var textFieldsArray: [UITextField]?
Connect all text fields to the above property.
Then you can just iterate over all the textFields using the for-in loop in swift, get values, and calculate the average.
If you use objective-C code, connect all outlets to IBOutletCollection, and calculate the average using #avg from KVC collection operators.
Use IBOuletCollection rather than individual IBOulet for UITextField. And just iterate into the collection and get the value of each textfield save it into variable and than get the average of those values.
var allValues = 0
for tf in txtFields {
allValues = allValues + Int(tf.text!)!
}
print(allValues)

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.

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