UIAlertController

Aus Wikizone
Version vom 11. Januar 2023, 13:35 Uhr von 134.3.86.14 (Diskussion)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche

Links[Bearbeiten]

UIKit Framework

Beispiele[Bearbeiten]

In diesem Beispiel sind ein paar Alerts angelegt. Es gibt im View ein Label und ein paar Buttons. Interessant ist das CustomAlert. Es ist möglich vollständig eigene Designs zu erzeugen. Am saubersten funktioniert das wenn man das Delegate Pattern nutzt.

//
//  ViewController.swift
//  UIAlert Demo
//
//  Created by Stephan Schlegel on 08.01.23.
//

import UIKit

class ViewController: UIViewController, CustomAlertDelegate {
    
    let customAlert = CustomAlert()
    
    @IBOutlet weak var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        customAlert.delegate = self // catch up delegate of custom alert
    }

    @IBAction func buttonTapped(_ sender: UIButton) {
        print("Button \(sender.tag) tapped")
        
        /**
         Note that showInput1 and showInput2 gives an Constraint Error in XCode 14
         when they open (maybe a bug as it's the normal implementation.
         The customAlert gives none because of it's
         translatesAutoresizingMaskIntoConstraints = false
         but this means it have to set it's own constrains
         */
        if sender.tag == 1{
            showAlert()
        }else if sender.tag == 2{
            showSelection()
        }else if sender.tag == 3 {
            showInput1()
        }else if sender.tag == 4 {
            showInput2()
        }else if sender.tag == 5 {
            showCustomAlert()
        }
    }
    
    func alertDidDismissWithInput(_ input: String?) {
        // Handle the input here
        if(input != nil){
            print("user input: \(input ?? "")")
            label.text = "Your input: \(input ?? "")"
        }
    }
    
    private func showAlert(){
        let alertController = UIAlertController(title: "Error", message: "Invalaid email address", preferredStyle: .alert)
        let dismissAction = UIAlertAction.init(title: "Dismiss", style: .default)
        alertController.addAction(dismissAction)
        present(alertController, animated: true, completion: nil)
    }
    
    private func showSelection(){
        let alertController = UIAlertController(title: "Confirmation", message: "Select an item", preferredStyle: .alert)
        let appleAction = UIAlertAction(title: "Apple ????", style: .default){ _ in
            self.label.text = "Eating apples ????"
        }
        let orangeAction = UIAlertAction(title: "Orange ????", style: .default){ _ in
            self.label.text = "Eating an orange ????"
        }
        let cherryAction = UIAlertAction(title: "Cherry ????", style: .default){ _ in
            self.label.text = "Eating cherries ????"
        }
        alertController.addAction(appleAction)
        alertController.addAction(orangeAction)
        alertController.addAction(cherryAction)
        present(alertController,animated: true,completion: {
            print("selection done")
        })
    }
    
    private func showInput1(){
        let alertController = UIAlertController(title: "Text-Eingabe", message: "Gib deinen Namen ein:", preferredStyle: .alert)
        // add text field
        alertController.addTextField { (textField) in
            textField.placeholder = "Name"
        }
        let okAction = UIAlertAction(title: "OK", style: .default) { (action) in
            let name = alertController.textFields?[0].text
            print("Dein Name ist: \(name ?? "na")")
        }

        alertController.addAction(okAction)

        present(alertController, animated: true, completion: nil)
    }
    
    private func showInput2(){
        let alertController = UIAlertController(title: "Login", message: "Enter name and password", preferredStyle: .alert)
        alertController.addTextField(configurationHandler: nil)
        alertController.addTextField{ textField in
            textField.isSecureTextEntry = true
        }
        let okAction = UIAlertAction(title: "OK", style: .default){ _ in
            var _name = String()
            var _password = String()
            
            if let nameTextField = alertController.textFields?.first,
               let name = nameTextField.text{
                    _name = name
            }
            if let passwordTextField = alertController.textFields?.last,
               let password = passwordTextField.text{
                    _password = password
            }
            self.label.text = _name + " " + _password
        }
        alertController.addAction(okAction)
        present(alertController, animated: true)
    }
    
    private func showCustomAlert() {
        self.customAlert.alertTitle = "Custom Alert"
        present(self.customAlert, animated: true, completion: nil)
    }
}
//
//  CustomAlert.swift
//  UIAlert Demo
//
//  Created by Stephan Schlegel on 10.01.23.
//

import UIKit

// protocol for delegate pattern
protocol CustomAlertDelegate: AnyObject {
    func alertDidDismissWithInput(_ input: String?)
}

class CustomAlert: UIViewController {
    weak var delegate: CustomAlertDelegate?
    
    // Code for creating UI elements
    var alertTitle: String?
    var inputTextField: UITextField?
    var okButton: UIButton?
    var dismissButton: UIButton?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Create the alert title label
        let titleLabel = UILabel()
        titleLabel.text = alertTitle
        titleLabel.textAlignment = .center
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(titleLabel)
        
        // Create the text input field
        inputTextField = UITextField()
        inputTextField?.placeholder = "Enter some text"
        inputTextField?.borderStyle = .roundedRect
        inputTextField?.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(inputTextField!)
        
        // Create the "OK" button
        okButton = UIButton(type: .system)
        okButton?.backgroundColor = .systemFill
        okButton?.setTitleColor(.white, for: .normal)
        okButton?.setTitle("OK", for: .normal)
        okButton?.titleLabel?.textAlignment = .center
        okButton?.layer.borderWidth = 1
        okButton?.layer.borderColor = UIColor.black.cgColor
        okButton?.addTarget(self, action: #selector(okButtonTapped), for: .touchUpInside)
        okButton?.translatesAutoresizingMaskIntoConstraints = false
        //view.addSubview(okButton!)
        
        // Create the "Dismiss" button
        dismissButton = UIButton(type: .system)
        dismissButton?.backgroundColor = .systemFill
        dismissButton?.setTitleColor(.white, for: .normal)
        dismissButton?.setTitle("Dismiss", for: .normal)
        dismissButton?.titleLabel?.textAlignment = .center
        dismissButton?.layer.borderWidth = 1
        dismissButton?.layer.borderColor = UIColor.black.cgColor
        dismissButton?.addTarget(self, action: #selector(dismissButtonTapped), for: .touchUpInside)
        dismissButton?.translatesAutoresizingMaskIntoConstraints = false
        //view.addSubview(dismissButton!)
        
        // Create a stack view to hold the buttons
        let stackView = UIStackView(arrangedSubviews: [okButton!, dismissButton!])
        stackView.axis = .horizontal
        stackView.spacing = 20
        stackView.distribution = .fillEqually
        
        stackView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stackView)
        // Set the background color of the alert
        //view.backgroundColor = UIColor.lightGray
        
        // Add constraints to position the elements in the alert
        // constraint need to be add in detail
        let margins = view.layoutMarginsGuide
        
        NSLayoutConstraint.activate([
            titleLabel.topAnchor.constraint(equalTo: margins.topAnchor, constant: 20),
            titleLabel.leadingAnchor.constraint(equalTo: margins.leadingAnchor),
            titleLabel.trailingAnchor.constraint(equalTo: margins.trailingAnchor),
            
            inputTextField!.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 20),
            inputTextField!.leadingAnchor.constraint(equalTo: margins.leadingAnchor, constant: 20),
            inputTextField!.trailingAnchor.constraint(equalTo: margins.trailingAnchor, constant: -20),
            
            // Add constraints to position the stack view
            
            stackView.topAnchor.constraint(equalTo: inputTextField!.bottomAnchor, constant: 20),
            stackView.leadingAnchor.constraint(equalTo: margins.leadingAnchor, constant: 20),
            stackView.trailingAnchor.constraint(equalTo: margins.trailingAnchor, constant: -20)
        ])
    }
    
    @objc func okButtonTapped() {
        let input = inputTextField!.text
        delegate?.alertDidDismissWithInput(input)
        self.dismiss(animated: true, completion: nil) // close modal
    }
    
    @objc func dismissButtonTapped() {
        delegate?.alertDidDismissWithInput(nil)
        self.dismiss(animated: true, completion: nil) // close modal
    }
    
    /**
     when the user taps the "OK" button, the custom alert will pass the user input to the `alertDidDismissWithInput` method of the view controller by calling `delegate?.alertDidDismissWithInput(input)`.
     When user taps the "Dismiss" button, the custom alert will call `delegate?.alertDidDismissWithInput(nil)`  which will pass nil in the input parameter of the method and the view controller can handle this accordingly.
     
     This way by using delegation pattern, the view controller can handle the input separately from the presentation of the custom alert.
     */
}