I am in the process of programming a small app to calculate exposure times.
I have a UiViewController to set the apertures of one Stop, halfStop and thridStop via three UiSwitches.
If you set one UiSwitch to .isON == true, the other two switch to .isOn == false. This also works perfectly.
I also have a button that can be used to return to the previous ViewController. UiSwitch states should be saved with a tap on this button.
If one of the switches is selected, the corresponding array should be displayed in the PickerView.
This works perfectly with a single array, but I can't manage with several.
And that's the problem, I've read a lot here and tried a lot, but it just doesn't work.
Here is the codes as I have written it so far:
ApertureModel:
class ApertureModel {
var aperture: String
var f: Double
init(_aperture: String, _f: Double) {
self.aperture = _aperture
self.f = _f
}
}
Aperture Data
import Foundation
class ApertureData {
class func DataOneStop() -> [ApertureModel] {
var dataAperture = [ApertureModel]()
dataAperture.append(ApertureModel(_aperture: "f:0.5", _f: 0.5))
dataAperture.append(ApertureModel(_aperture: "f:0.7", _f: 0.7))
dataAperture.append(ApertureModel(_aperture: "f:1.0", _f: 1.0))
dataAperture.append(ApertureModel(_aperture: "f:1.1", _f: 1.1))
dataAperture.append(ApertureModel(_aperture: "f:1.2", _f: 1.2))
dataAperture.append(ApertureModel(_aperture: "f:1.4", _f: 1.4))
dataAperture.append(ApertureModel(_aperture: "f:1.6", _f: 1.6))
dataAperture.append(ApertureModel(_aperture: "f:1.8", _f: 1.8))
dataAperture.append(ApertureModel(_aperture: "f:2.0", _f: 2.0))
dataAperture.append(ApertureModel(_aperture: "f:2.2", _f: 2.2))
dataAperture.append(ApertureModel(_aperture: "f:2.5", _f: 2.5))
dataAperture.append(ApertureModel(_aperture: "f:2.8", _f: 2.8))
dataAperture.append(ApertureModel(_aperture: "f:3.2", _f: 3.2))
dataAperture.append(ApertureModel(_aperture: "f:4.0", _f: 4.0))
dataAperture.append(ApertureModel(_aperture: "f:4.5", _f: 4.5))
dataAperture.append(ApertureModel(_aperture: "f:5.0", _f: 5.0))
dataAperture.append(ApertureModel(_aperture: "f:5.6", _f: 5.6))
dataAperture.append(ApertureModel(_aperture: "f:6.3", _f: 6.3))
dataAperture.append(ApertureModel(_aperture: "f:7.2", _f: 7.2))
dataAperture.append(ApertureModel(_aperture: "f:8.0", _f: 8.0))
dataAperture.append(ApertureModel(_aperture: "f:9.0", _f: 9.0))
dataAperture.append(ApertureModel(_aperture: "f:10", _f: 10.0))
dataAperture.append(ApertureModel(_aperture: "f:11", _f: 11.0))
dataAperture.append(ApertureModel(_aperture: "f:13", _f: 13.0))
dataAperture.append(ApertureModel(_aperture: "f:14", _f: 14.0))
dataAperture.append(ApertureModel(_aperture: "f:16", _f: 16.0))
dataAperture.append(ApertureModel(_aperture: "f:18", _f: 18.0))
dataAperture.append(ApertureModel(_aperture: "f:20", _f: 20.0))
dataAperture.append(ApertureModel(_aperture: "f:22", _f: 22.0))
dataAperture.append(ApertureModel(_aperture: "f:25", _f: 22.0))
dataAperture.append(ApertureModel(_aperture: "f:29", _f: 29.0))
dataAperture.append(ApertureModel(_aperture: "f:32", _f: 32.0))
dataAperture.append(ApertureModel(_aperture: "f:36", _f: 36.0))
dataAperture.append(ApertureModel(_aperture: "f:40", _f: 40.0))
dataAperture.append(ApertureModel(_aperture: "f:45", _f: 45.0))
dataAperture.append(ApertureModel(_aperture: "f:64", _f: 64.0))
dataAperture.append(ApertureModel(_aperture: "f:90", _f: 90.0))
dataAperture.append(ApertureModel(_aperture: "f:128", _f: 128.0))
dataAperture.append(ApertureModel(_aperture: "f:256", _f: 256.0))
dataAperture.append(ApertureModel(_aperture: "f:512", _f: 512.0))
dataAperture.append(ApertureModel(_aperture: "f:1024", _f: 1024.0))
return dataAperture
}
class func DataHalfStop() -> [ApertureModel] {
var dataAperture = [ApertureModel]()
dataAperture.append(ApertureModel(_aperture: "f/1.0", _f: 1.0))
dataAperture.append(ApertureModel(_aperture: "f/1.2", _f: 1.2))
dataAperture.append(ApertureModel(_aperture: "f/1.4", _f: 1.4))
dataAperture.append(ApertureModel(_aperture: "f/1.7", _f: 1.7))
dataAperture.append(ApertureModel(_aperture: "f/2.0", _f: 2.0))
dataAperture.append(ApertureModel(_aperture: "f/2.4", _f: 2.4))
dataAperture.append(ApertureModel(_aperture: "f/2.8", _f: 2.8))
dataAperture.append(ApertureModel(_aperture: "f/3.3", _f: 3.3))
dataAperture.append(ApertureModel(_aperture: "f/4.0", _f: 4.0))
dataAperture.append(ApertureModel(_aperture: "f/4.8", _f: 4.8))
dataAperture.append(ApertureModel(_aperture: "f/5.6", _f: 5.6))
dataAperture.append(ApertureModel(_aperture: "f/6.7", _f: 6.7))
dataAperture.append(ApertureModel(_aperture: "f/8.0", _f: 8.0))
dataAperture.append(ApertureModel(_aperture: "f/9.5", _f: 9.5))
dataAperture.append(ApertureModel(_aperture: "f/10", _f: 10.0))
dataAperture.append(ApertureModel(_aperture: "f/11", _f: 11.0))
dataAperture.append(ApertureModel(_aperture: "f/14", _f: 14.0))
dataAperture.append(ApertureModel(_aperture: "f/16", _f: 16.0))
dataAperture.append(ApertureModel(_aperture: "f/19", _f: 19.0))
dataAperture.append(ApertureModel(_aperture: "f/22", _f: 22.0))
dataAperture.append(ApertureModel(_aperture: "f/27", _f: 27.0))
dataAperture.append(ApertureModel(_aperture: "f/32", _f: 32.0))
dataAperture.append(ApertureModel(_aperture: "f/38", _f: 38.0))
dataAperture.append(ApertureModel(_aperture: "f/45", _f: 45.0))
dataAperture.append(ApertureModel(_aperture: "f/54", _f: 54.0))
dataAperture.append(ApertureModel(_aperture: "f/64", _f: 64.0))
dataAperture.append(ApertureModel(_aperture: "f/76", _f: 76.0))
dataAperture.append(ApertureModel(_aperture: "f/107", _f: 107.0))
dataAperture.append(ApertureModel(_aperture: "f/128", _f: 128.0))
dataAperture.append(ApertureModel(_aperture: "f/215", _f: 215.0))
dataAperture.append(ApertureModel(_aperture: "f/256", _f: 253.0))
dataAperture.append(ApertureModel(_aperture: "f/430", _f: 430.0))
dataAperture.append(ApertureModel(_aperture: "f/512", _f: 512.0))
dataAperture.append(ApertureModel(_aperture: "f/860", _f: 860.0))
dataAperture.append(ApertureModel(_aperture: "f/1024", _f: 1024.0))
return dataAperture
}
class func DataThirdStop() -> [ApertureModel] {
var dataAperture = [ApertureModel]()
dataAperture.append(ApertureModel(_aperture: "f/1.0", _f: 1.0))
dataAperture.append(ApertureModel(_aperture: "f/1.4", _f: 1.4))
dataAperture.append(ApertureModel(_aperture: "f/2.0", _f: 2.0))
dataAperture.append(ApertureModel(_aperture: "f/2.8", _f: 2.8))
dataAperture.append(ApertureModel(_aperture: "f/4.0", _f: 4.0))
dataAperture.append(ApertureModel(_aperture: "f/5.6", _f: 5.6))
dataAperture.append(ApertureModel(_aperture: "f/8.0", _f: 8.0))
dataAperture.append(ApertureModel(_aperture: "f/11", _f: 11.0))
dataAperture.append(ApertureModel(_aperture: "f/16", _f: 16.0))
dataAperture.append(ApertureModel(_aperture: "f/22", _f: 22.0))
dataAperture.append(ApertureModel(_aperture: "f/32", _f: 32.0))
dataAperture.append(ApertureModel(_aperture: "f/45", _f: 45.0))
dataAperture.append(ApertureModel(_aperture: "f/64", _f: 64.0))
dataAperture.append(ApertureModel(_aperture: "f/90", _f: 90.0))
dataAperture.append(ApertureModel(_aperture: "f/128", _f: 128.0))
dataAperture.append(ApertureModel(_aperture: "f/256", _f: 256.0))
dataAperture.append(ApertureModel(_aperture: "f/512", _f: 512.0))
dataAperture.append(ApertureModel(_aperture: "f/1024", _f: 1024.0))
return dataAperture
}
}
PickerView
import UIKit
class SelectAperture: UIViewController {
@IBOutlet weak var aperturePicker: UIPickerView!
var delegateAperture: apertureDelegate? = nil
var apertureModelThird = [ApertureModel]()
let defaults = UserDefaults.standard
//MARK: - Unwind
@IBAction func unwindAperture(_ sender: UIStoryboardSegue) {
dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
aperturePicker.dataSource = self
aperturePicker.delegate = self
apertureModelThird = ApertureData.DataOneStop()
//MARK: - Notification
if let selectedRow = defaults.object(forKey: "saveAperturePicker") as? Int {
aperturePicker.selectRow(selectedRow, inComponent: 0, animated: true)
}
NotificationCenter.default.addObserver(self, selector: #selector(aperturePickerChanged), name: Notification.Name.pickersChanged, object: nil)
}
//MARK: - Func PickerChanced
@objc func aperturePickerChanged() {
let values = aperturePicker.selectedRow(inComponent: 0)
_ = apertureModelThird[values...values]
}
}
//MARK: - PickerView Delegate
extension SelectAperture: UIPickerViewDelegate {
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
apertureModelThird[row].aperture
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
NotificationCenter.default.post(name: Notification.Name.pickersChanged, object: self)
//MARK: - Speicherung der PickerRow
let rowDefaults = defaults
rowDefaults.set(row, forKey: "saveAperturePicker")
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let pickerText = UILabel()
pickerText.textColor = UIColor.white
pickerText.text = apertureModelThird[row].aperture
pickerText.font = UIFont.boldSystemFont(ofSize: 20)
pickerText.textAlignment = NSTextAlignment.center
return pickerText
}
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
30
}
}
//MARK: - PickerView DataSource
extension SelectAperture: UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
apertureModelThird.count
}
}
//MARK: - Extension Notification
extension Notification.Name {
static let pickersChanged = Notification.Name("PickerChanged")
}
//MARK: - Delegate
protocol apertureDelegate {
func apertureValue(aperture: String)
}
UISwitches
import UIKit
class SelectApertureStops: UIViewController {
@IBOutlet weak var oneStopSwitch: UISwitch!
@IBOutlet weak var halfStopSwitch: UISwitch!
@IBOutlet weak var thirdStopSwitch: UISwitch!
let switchDelfault = UserDefaults.standard
//MARK: - Unwind
@IBAction func unwindStops(_ sender: UIStoryboardSegue) {
dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
oneStopSwitch.isOn = switchDelfault.bool(forKey: "switchStateOne")
halfStopSwitch.isOn = switchDelfault.bool(forKey: "switchStateHalf")
thirdStopSwitch.isOn = switchDelfault.bool(forKey: "switchStateThird")
}
@IBAction func oneStopSwitchChanged(_ sender: UISwitch) {
if (sender.isOn == true) {
halfStopSwitch.isOn = false
thirdStopSwitch.isOn = false
} else if sender.isOn == false && halfStopSwitch.isOn == false && thirdStopSwitch.isOn == false {
oneStopSwitch.isOn = true
}
switchDelfault.set(sender.isOn, forKey: "switchStateOne")
}
@IBAction func halfStopSwitchChanged(_ sender: UISwitch) {
if sender.isOn == true {
oneStopSwitch.isOn = false
thirdStopSwitch.isOn = false
} else if oneStopSwitch.isOn == false && halfStopSwitch.isOn == false && thirdStopSwitch.isOn == false {
halfStopSwitch.isOn = true
}
switchDelfault.set(sender.isOn, forKey: "switchStateHalf")
}
@IBAction func thirdStopSwitchChanged(_ sender: UISwitch) {
if sender.isOn == true {
oneStopSwitch.isOn = false
halfStopSwitch.isOn = false
} else if oneStopSwitch.isOn == false && halfStopSwitch.isOn == false && thirdStopSwitch.isOn == false {
thirdStopSwitch.isOn = true
}
switchDelfault.set(sender.isOn, forKey: "switchStateThird")
}
}
I would be very happy if you could help me, because I just can't get any further.
I'm still a beginner in Swift5, I've learnt a lot in the meantime, but unfortunately I'm failing with this problem.
The solution below provides a simplified approach to the problem you outline.
It uses an enum to track the active switch, and then uses that to drive the updates to the pickers' content through the
pickerView(_:titleForRow:forComponent:)delegate method and the state of the switches.It also uses a single method to handle changes in all 3 switches. In the solution below I use code to generate the UI components so that it forms a working example. You'd need to adapt it to use your IB elements, but the same principles would apply.
[I've just thrown the UI elements into stack views to keep things simple]