Im trying to change the UIBackground with colors provided in a picker. I have the picker working fine and can print the selected color, however my problem is getting the selectedColor to change the UIBackground with the push of the selectedColorButton. I thought I could pass in the selectedColor at the end of view.backgroundColor = UIColor., but I can't get it to work and I guess going about it incorrectly.
Thanks!
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource{
let colors = ["Red", "Green", "Orange", "Yellow", "Pink", "Purple"]
var selectedColor = ""
@IBAction func selectedColorButton(_ sender: UIButton) {
// view.backgroundColor = UIColor.
}
@IBOutlet weak var pickerView: UIPickerView!
override func viewDidLoad() {
super.viewDidLoad()
pickerView.delegate = self
pickerView.dataSource = self
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return colors.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return colors[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
return selectedColor = colors[row]
}
}
CodePudding user response:
As you've discovered view.backgroundColor expects a value of type UIColor and unfortunately all you have available is a String. There's no direct conversion but there are two approaches you can take here:
- Run a second array that contains UIColor values
You're presenting your picker options using a colors array here:
let colors = ["Red", "Green", "Orange", "Yellow", "Pink", "Purple"]
You can replace that implementation with a second array that contains the actual UIColor values in the same order. Now, instead of tracking the selected name, track the selected index
var selectedIndex = 0
let colorNames = ["Red", "Green", "Orange", "Yellow", "Pink", "Purple"]
let colors: [UIColor] = [.red, .green, .orange, .yellow, .pink, .purple]
Present your options using colorNames, then use the index to access colors
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedIndex = row
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return colorNames[row]
}
@IBAction func selectedColorButton(_ sender: UIButton) {
view.backgroundColor = colors[selectedIndex]
}
- Use a system property for the names
Instead of having a separate array just to store the names, we can use the accessibility names of the colors. Now, all we need is a colors array and we can directly store the selected color, no index tracking or name selection
var selectedColor: UIColor? = nil
let colors: [UIColor] = [.red, .green, .orange, .yellow, .pink, .purple]
Now present those color options and use their accessibilityName properties for the names
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedColor = colors[row]
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return colors[row].accessibilityName
}
@IBAction func selectedColorButton(_ sender: UIButton) {
if let color = selectedColor {
view.backgroundColor = color
}
}
The advantage of the first approach is that we get to control the names. The advantage of the second approach is that we save the memory for the extra information. Your choice!
You can even try other approaches, like using an enum or a tuple or even your own classes. I suggest you try them all!
CodePudding user response:
The main issue is you have a list a colors that are Strings, but you need UIColors to use as a color for the background. I think the best way is to make use of a Dictionary, so each row has a name and a UIColor.
The function selectedColorButton was not doing anything and was not needed so I removed it.
Here is the full code:
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource{
let colors = [["name": "Red", "color": UIColor.red],
["name": "Green", "color": UIColor.green],
["name": "Orange", "color": UIColor.orange],
["name": "Yellow", "color": UIColor.yellow],
["name": "Pink", "color": UIColor.magenta],
["name": "Purple", "color": UIColor.purple]]
@IBOutlet weak var pickerView: UIPickerView!
override func viewDidLoad() {
super.viewDidLoad()
pickerView.delegate = self
pickerView.dataSource = self
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return colors.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if let name = colors[row]["name"] as? String {
return name
}
return nil
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if let color = colors[row]["color"] as? UIColor {
view.backgroundColor = color
}
}
}
