How to use UIColorPickerViewController in Swift?

UIColorPicker ScreenShot.png

WWDC20 is officially over, and iOS 14 is here, and with it came so many new features. Creating apps for all the Apple platforms is now one click away. I am so excited to share with you guys about all the new things introduced in WWDC20, starting with this article, there’s going to be so much more. So subscribe now to stay updated about my upcoming articles.

Note: For this tutorial, you will need Xcode 12, at the time of writing this article, Xcode 12 is available as a beta version for download on this link.

Let’s Start

I have kept this article simple and easy for you guys to follow, so in this project, we will be changing the background color of the UIView on the basis of color selected by the user.

Create a new Xcode Project. Make sure you have selected Storyboard as Interface while creating the project and not SwiftUI.

UIColorPickerViewController is a beautiful way of picking colors not just in iOS, but across all the Apple platforms, with this beauty, it’s so easy to use for a user, and with only a few lines of code, you can have your color picker running in your system. Let’s dive into an example now.

Open the Main.storyboard file, and add a Button in your ViewController.

Next, add two alignment constraints to the button. (Refer Screenshot)

  • Horizontally in Container

  • Vertically in Container

Button Constraints.png

Next, create an action of your button, name it changeBackground as mentioned in the image below

Enough of Storyboard, Now let’s move on to the Code.

Code

There are two ways of getting the selected color from the picker, one with the help of a delegate, second with the help of Combine. I love working with Combine, but I’ll show you both ways of receiving the selected color.

Open your ViewController.swift file, and in your newly created action changeBackground, add the code shown below.

// Initializing Color Picker
let picker = UIColorPickerViewController()

// Setting the Initial Color of the Picker
picker.selectedColor = self.view.backgroundColor!

// Setting Delegate
picker.delegate = self

// Presenting the Color Picker
self.present(picker, animated: true, completion: nil)

In the code above, we have initialized the UIColorPickerViewController with a preset color, so whenever the color picker is shown, the background color of the UIView is shown as the selected color. Next, we set a delegate and the present it over our current view controller.

With this done, we need to add an extension at the bottom of our ViewController.swift file. Add the code shown below.

extension ViewController: UIColorPickerViewControllerDelegate {
    
    //  Called once you have finished picking the color.
    func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) {
        self.view.backgroundColor = viewController.selectedColor
        
    }
    
    //  Called on every color selection done in the picker.
    func colorPickerViewControllerDidSelectColor(_ viewController: UIColorPickerViewController) {
            self.view.backgroundColor = viewController.selectedColor
    }
}

Both the protocol functions are optional, and you can use them as per your convenience.

colorPickerViewControllerDidFinish(_:) function is used to receive the callback once the user has completed the action of selecting the color and want to come back to the previous screen.

colorPickerViewControllerDidSelectColor(_:) function is used to receive the callback on every selection of color done in the Color Picker.

So this was the delegate way of receiving the user input, Now let's look at how we can achieve this with Combine.

We no longer need the extension which we just added for the demo purpose, nor we need to set a delegate in the changeBackground action function.

Combine is available in almost all of your data types, I have already discussed this in my previous articles about Combine. If you haven't read them, I'll recommend you to read them, and I'll drop a link at the end of this article to all the articles related to Combine.

Let’s start with adding import Combine on top of your ViewController.swift file, so that we have access to the objects of Combine framework.

Next, match your code with the code shown below.

// Global declaration, to keep the subscription alive.
var cancellable: AnyCancellable?

@IBAction func changeBackground(_ sender: Any) {
    
    let picker = UIColorPickerViewController()
    picker.selectedColor = self.view.backgroundColor!
    
    //  Subscribing selectedColor property changes.
    self.cancellable = picker.publisher(for: \.selectedColor)
        .sink { color in
            
            //  Changing view color on main thread.
            DispatchQueue.main.async {
                self.view.backgroundColor = color
            }
        }
    
    self.present(picker, animated: true, completion: nil)
}

We have declared a global variable to keep receiving the changes published by the Publisher, even when the changeBackground function is not in scope.

Next, the change we have done in the changeBackground function is subscribing the selectedColor property with the help of KeyPath.

Run the application.

Background Color Change.gif

Click Here to download the final project.

With the help of Combine we can reduce our delegate function needs, and this also helps you maintain the code easily.

I hope you guys enjoyed reading my article. There’s a lot more to learn together, so subscribe to stay updated about my upcoming articles.

If you have any suggestions or questions, Feel free to connect me on Twitter or Reddit. 😉

To read articles related to Combine, Click Here.

New UIDatePicker in iOS 14

Combine - Creating your own Publishers with PassthroughSubject and CurrentValueSubject