Color Picker in iOS, iPadOS and macOS

WWDC 2020 brought many new UIControl APIs to iOS, iPadOS and macOS. One of the best new additions is the system Color Picker. Here are some of the main features of this new control-

  • Native- adapts to system fonts, themes.
  • Powerful- Colors can be picked from 3 different modes and it provides a screen picker which can be used to pick colors from anywhere on the screen
  • Transferable Pallets- Picked colors from the color picker can be accessed from anywhere.
  • Universal- Available on iOS, iPadOS and with Catalyst on macOS

Let’s code

The first thing we’ll do is configure our parent view controller. For this example we’ll change the background color of this view controller when the color picker view controller returns us a new color. We’ll store this color property in a variable called pickedColor. Let us initially set its value to UIColor.systemTeal because, fun fact, Teal is my favorite color. We have to create another property that is an object of the brand new UIColorPickerViewController class. We’ll call this object colorPicker.

Your class properties should now look like this:

private var pickedColor = UIColor.systemTeal
private var colorPicker = UIColorPickerViewController()

Creating a selectColor Function

This function will be used to configure and present the ColorPicker view controller on top of our parent view controller. Using the colorPicker variable we can access several properties of the CPVC such as setting the initial color, setting a settingAlpha boolean that will let users choose the opacity/alpha of the color. The function should now look like this

private func selectColor() {
    colorPicker.supportsAlpha = true
    colorPicker.selectedColor = pickedColor
    self.present(colorPicker, animated: true)
}

Setting up the Bar Button

Our color picker view controller will be presented when we tap on a right bar button item in a navigation bar. For this we’ll create a function that will setup the bar button and configure it’s action. We’ll first create a UIAction that will call the selectColor() function that we just built.

private func setupBarButton() {
    let pickColorAction = UIAction(title: "Pick Color") { _ in
        self.selectColor()
    }
    let pickColorBarButton = UIBarButtonItem(image: UIImage(systemName: "eyedropper"), primaryAction: pickColorAction)
    navigationItem.rightBarButtonItem = pickColorBarButton
}

Wiring up the Delegates

UIColorPickerViewController contains a UIColorPickerViewControllerDelegate that can inform the delegate on

  • didSelectColor - User has picked a color
  • didFinish- User has dismissed the color picker

To use these delegates we’ll extend the ViewController class and add conformance to the delegate. Below the closing bracket of the main class declaration write this

extension ViewController: UIColorPickerViewControllerDelegate {
}

Both the above mentioned delegate properties are optional but you’d want to use at lease one of them. For this example we’ll use both of the delegates just so that you understand when and how the delegate methods get called.
In the class extension add these two delegate methods

func colorPickerViewControllerDidSelectColor(_ viewController: UIColorPickerViewController) {
}
func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) {
}

The delegate method names are pretty self explanatory as with all Swift APIs. In the didSelectColor method we’ll first set the picked color to our pickedColor variable and then set the value of the view’s background color to pickedColor. Simple

func colorPickerViewControllerDidSelectColor(_ viewController: UIColorPickerViewController) {
    pickedColor = viewController.selectedColor
    view.backgroundColor = pickedColor
}

You can choose to do this in the didFinish method as well but for this example I’ll simply put a print statement to print a message to our Xcode console when the view is dismissed.

func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) {
    print("Color Picker Controller Did Finish")
}

Configuring in viewDidLoad

Now that we have most of our app ready all we need to do is to set the initial background color of our view, configure the barButtonItem and set the delegate. This is how my viewDidLoad method looks like

override func viewDidLoad() {
    super.viewDidLoad()
    colorPicker.delegate = self
    setupBarButton()
    view.backgroundColor = pickedColor
}

And that’s it. You now have a fully functioning, powerful and native color picker that you can use anywhere in your app.

If you liked this article you can

Thank you for reading this tutorial and if you have any questions feel free to ping me on Twitter @SwapnanilDhol