swift5uiswitchuialertaction

How to add UISwitch to UIAlertAction after adding image and text in Swift 5.1


I want to add UISwitch in to UIAlertAction after adding the image and text. I tried different ways but it's not working properly can someone help me to how to do this and appreciate your comments and feedback. please, refer attached code and screenshot for more details. I have shown places which i need to add UISwitch via red color arrows.

Source code

import UIKit

class ViewController: UIViewController {
    
    override func loadView() {
        super.loadView()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        //
        
    }
    
    override func viewWillLayoutSubviews() {
       let width = self.view.frame.width
       let navigationBar: UINavigationBar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: width, height: 44))
       self.view.addSubview(navigationBar);
       let navigationItem = UINavigationItem(title: "Navigation bar")
       let rightButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(openMenuPopHandler(_:)))
       navigationItem.rightBarButtonItem = rightButton
       navigationBar.setItems([navigationItem], animated: false)
    }
    
    
    @IBAction func openMenuPopHandler(_ sender: UIBarButtonItem) {
        let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
        
        let action1 = UIAlertAction(title: "Action 1", style: .default) { (action) in
            //TODO Action 1 impl
        }
        let icon1 = UIImage(systemName: "music.note", withConfiguration: UIImage.SymbolConfiguration(pointSize: 30, weight: .bold))?.withTintColor(.black)
        action1.setValue(icon1?.withRenderingMode(.alwaysOriginal), forKey: "image")
        action1.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
        action1.setValue(UIColor.black, forKey: "titleTextColor")
        
        let action2 = UIAlertAction(title: "Action 2", style: .default) { (action) in
            //TODO Action 2 impl
        }
        let icon2 = UIImage(systemName: "music.note", withConfiguration: UIImage.SymbolConfiguration(pointSize: 30, weight: .bold))?.withTintColor(.black)
        action2.setValue(icon2?.withRenderingMode(.alwaysOriginal), forKey: "image")
        action2.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
        action2.setValue(UIColor.black, forKey: "titleTextColor")
        
        alertController.addAction(action1)
        alertController.addAction(action2)
        
        alertController.modalPresentationStyle = .popover
        
        let presentationController = alertController.popoverPresentationController
        presentationController?.barButtonItem = sender
        present(alertController, animated: true, completion: nil)
        
        let subview = (alertController.view.subviews.first?.subviews.first?.subviews.first!)! as UIView
        subview.layer.cornerRadius = 0
        subview.backgroundColor = .white
    }
    
    
} 

screenshot


Solution

  • Finally, i was able to do it. sorry for late replying this. We have a key, it is called contentViewController and it is used for customize UI elements inside of UIAlertAction. so please, checkout my latest code and try it. i have attached screenshot for final output. Thanks...

    Code:

    import UIKit
    
    class ViewController: UIViewController {
        
        class UISwitchController: UIViewController {
            var uiSwitch: UISwitch!
            
            init(){
                self.uiSwitch = UISwitch()
                super.init(nibName: nil, bundle: nil)
            }
            
            required init?(coder: NSCoder) {
                fatalError("init(coder:) has not been implemented")
            }
            
            override func viewDidLoad() {
                super.viewDidLoad()
                uiSwitch.addTarget(self, action: #selector(siwtchOperation(_:)), for: .touchUpInside)
                uiSwitch.translatesAutoresizingMaskIntoConstraints = false
                self.view.addSubview(uiSwitch)
            }
            
            @IBAction func siwtchOperation(_ sender: UISwitch){
                //TODO operation impl
            }
            
            func setPosition(){
                NSLayoutConstraint.activate([
                    uiSwitch.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -20),
                    uiSwitch.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
                    self.view.rightAnchor.constraint(equalTo: self.view.superview!.rightAnchor, constant: 0),
                    self.view.centerYAnchor.constraint(equalTo: self.view.superview!.centerYAnchor)
                ])
            }
            
            func setUiSwitchVal(isOn: Bool){
                uiSwitch.isOn = isOn
            }
            
        }
        
        override func loadView() {
            super.loadView()
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()
            //
            
        }
        
        
        override func viewWillLayoutSubviews() {
            let width = self.view.frame.width
            let navigationBar: UINavigationBar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: width, height: 44))
            self.view.addSubview(navigationBar);
            let navigationItem = UINavigationItem(title: "Navigation bar")
            let rightButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(openMenuPopHandler(_:)))
            navigationItem.rightBarButtonItem = rightButton
            navigationBar.setItems([navigationItem], animated: false)
        }
        
        
        @IBAction func openMenuPopHandler(_ sender: UIBarButtonItem) {
            let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
            
            let action1 = UIAlertAction(title: "Action 1", style: .default) { (action) in
                //TODO Action 1 impl
            }
            let uiSwitchController1 = UISwitchController()
            let icon1 = UIImage(systemName: "music.note", withConfiguration: UIImage.SymbolConfiguration(pointSize: 30, weight: .bold))?.withTintColor(.black)
            action1.setValue(icon1?.withRenderingMode(.alwaysOriginal), forKey: "image")
            action1.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
            action1.setValue(UIColor.black, forKey: "titleTextColor")
            action1.setValue(uiSwitchController1, forKey: "contentViewController")
            action1.isEnabled = false
            
            let action2 = UIAlertAction(title: "Action 2", style: .default) { (action) in
                //TODO Action 2 impl
            }
            let uiSwitchController2 = UISwitchController()
            let icon2 = UIImage(systemName: "music.note", withConfiguration: UIImage.SymbolConfiguration(pointSize: 30, weight: .bold))?.withTintColor(.black)
            action2.setValue(icon2?.withRenderingMode(.alwaysOriginal), forKey: "image")
            action2.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
            action2.setValue(UIColor.black, forKey: "titleTextColor")
            action2.setValue(uiSwitchController2, forKey: "contentViewController")
            action2.isEnabled = false
            
            alertController.addAction(action1)
            alertController.addAction(action2)
            
            alertController.modalPresentationStyle = .popover
            
            let presentationController = alertController.popoverPresentationController
            presentationController?.barButtonItem = sender
            present(alertController, animated: true, completion: nil)
            
            let subview = (alertController.view.subviews.first?.subviews.first?.subviews.first!)! as UIView
            subview.layer.cornerRadius = 0
            subview.backgroundColor = .white
            
            uiSwitchController1.setPosition()
            uiSwitchController1.setUiSwitchVal(isOn: true)
            uiSwitchController2.setPosition()
            uiSwitchController2.setUiSwitchVal(isOn: false)
        }
        
        
    }
    

    Result