Search code examples
swiftuialertcontrolleruialertaction

UIAlertController Alert action TextField need to be resized-error


Getting this error...

[LayoutConstraints] Changing the translatesAutoresizingMaskIntoConstraints property of a UICollectionViewCell that is managed by a UICollectionView is not supported, and will result in incorrect self-sizing. View: <_UIAlertControllerTextFieldViewCollectionCell: 0x7fe6a9f26000; frame = (0 0; 270 24); gestureRecognizers = <NSArray: 0x60000098edc0>; layer = <CALayer: 0x6000007c5cc0>>

From this...

func saveText()
{
    let ac = UIAlertController(title: "NAME IT", message: nil, preferredStyle: .alert)

    ac.addTextField()

    let submitAction = UIAlertAction(title: "SAVE", style: .default)
    {
       [unowned ac] _ in
       let answer = ac.textFields![0]
        
       if answer.text!.count < 1
       {
          self.view.backgroundColor = .red
       }
       else
       {
          self.view.backgroundColor = .green
       }
    }
    ac.addAction(submitAction)
    present(ac, animated: true)
}

I have played around with this for a while, I have tried to figure out if I can add my own textfield to use it too...

func addTextField()
{
    let textField = UITextField()
    textField.translatesAutoresizingMaskIntoConstraints = false
}

But no luck

I need to remove this error.

Thanks in advance

Oh, this didn't help at all https://www.hackingwithswift.com/example-code/uikit/how-to-add-a-uitextfield-to-a-uialertcontroller


Solution

  • Thanks for trying to help, couldn't waste more than a day waiting for a solution so I spent two hours on a workaround instead.

    I figured it would be mean of me not to share... OR rather nice that I spent the extra 20 mins to share my workaround. If anyone plays hero and wants to edit this, I am happy to delete the answer.

    import UIKit
    
    class ViewController: UIViewController
    {
        let textFieldView = UIView()
        let textFieldLabel = UILabel()
        let textFieldField = UITextField()
        let textFieldButton = UIButton()
    
        let WhiteUIColour: UIColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
        let LightGreyUIColour: UIColor = #colorLiteral(red: 0.921431005, green: 0.9214526415, blue: 0.9214410186, alpha: 1)
        let DarkBlueUIColour: UIColor = #colorLiteral(red: 0.01680417731, green: 0.1983509958, blue: 1, alpha: 1)
    
        let MediumGreyCGColour: CGColor = #colorLiteral(red: 0.7540688515, green: 0.7540867925, blue: 0.7540771365, alpha: 1)
    
        let bold17 = UIFont.boldSystemFont(ofSize: 17)
    
        let hel17 = UIFont (name: "Helvetica", size: 17)
        let hel20 = UIFont (name: "Helvetica", size: 20)
    
       // Create button to present the UIAlert with textField workaround view
        let yourButton = UIButton()
    
        func createYourButton()
        {
            view.addSubview(yourButton)
            yourButton.translatesAutoresizingMaskIntoConstraints = false
            yourButton.backgroundColor = .red
            yourButton.setTitle("TAP ME", for: .normal)
            yourButton.addTarget(self, action: #selector(saveButtonTap), for: .touchUpInside)
    
            NSLayoutConstraint.activate([
               yourButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
               yourButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),
               yourButton.widthAnchor.constraint(equalToConstant: 100),
               yourButton.heightAnchor.constraint(equalToConstant: 50),
            ])
        }
    
        @objc func saveButtonTap()
        {
           saveName()
        }
    
        func saveName()
        {
           textfieldUIAlert()
            
           DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(200), execute:
           {
                self.textFieldView.isHidden = false
           DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300), execute:
           {
                self.textFieldField.becomeFirstResponder()
           })
           })
        }
    
        func textfieldUIAlert()
        {
           view.addSubview(textFieldView)
        
           textFieldView.isHidden = true
           textFieldView.translatesAutoresizingMaskIntoConstraints = false
           textFieldView.backgroundColor = LightGreyUIColour
           textFieldView.layer.cornerRadius = 16
        
           textFieldView.addSubview(textFieldLabel)
        
           textFieldLabel.translatesAutoresizingMaskIntoConstraints = false
           textFieldLabel.textAlignment = .center
           textFieldLabel.font = bold17
           textFieldLabel.text = "NAME IT"
        
           textFieldView.addSubview(textFieldField)
    
           textFieldField.translatesAutoresizingMaskIntoConstraints = false
           textFieldField.backgroundColor = WhiteUIColour
           textFieldField.layer.borderColor = MediumGreyCGColour
           textFieldField.layer.borderWidth = 0.5
           textFieldField.layer .cornerRadius = 9
           textFieldField.font = hel20
           textFieldField.textAlignment = .center
        
           textFieldView.addSubview(textFieldButton)
        
           textFieldButton.translatesAutoresizingMaskIntoConstraints = false
           textFieldButton.setTitleColor(DarkBlueUIColour, for: .normal)
           textFieldButton.titleLabel?.font = hel17
           textFieldButton.setTitle("SAVE", for: .normal)
           textFieldButton.addTarget(self, action: #selector(textFieldButtonTap), for: .touchUpInside)
       
              NSLayoutConstraint.activate([
               textFieldView.topAnchor.constraint(equalTo: view.centerYAnchor, constant: -250),
               textFieldView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
               textFieldView.bottomAnchor.constraint(equalTo: view.centerYAnchor, constant: -90),
               textFieldView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 7/10),
            
               textFieldLabel.topAnchor.constraint(equalTo: textFieldView.topAnchor),
               textFieldLabel.centerXAnchor.constraint(equalTo: textFieldView.centerXAnchor),
               textFieldLabel.widthAnchor.constraint(equalTo: textFieldView.widthAnchor),
               textFieldLabel.heightAnchor.constraint(equalToConstant: 50),
            
               textFieldField.centerXAnchor.constraint(equalTo: textFieldView.centerXAnchor),
               textFieldField.centerYAnchor.constraint(equalTo: textFieldView.centerYAnchor, constant: -10),
               textFieldField.heightAnchor.constraint(equalToConstant: 33),
               textFieldField.widthAnchor.constraint(equalTo: textFieldView.widthAnchor, multiplier: 8.5/10),
            
               textFieldButton.topAnchor.constraint(equalTo: textFieldField.bottomAnchor, constant: 15),
               textFieldButton.bottomAnchor.constraint(equalTo: textFieldView.bottomAnchor),
               textFieldButton.centerXAnchor.constraint(equalTo: textFieldView.centerXAnchor),
               textFieldButton.widthAnchor.constraint(equalTo: textFieldView.widthAnchor),
              ])
         }
    
         @objc func textFieldButtonTap()
         {
             if textFieldField.text!.count < 1 || textFieldField.text == " " || textFieldField.text == "  " || textFieldField.text == "   "
             {
                 let TooShort = UIAlertController(title: "TOO SHORT", message: "\n\nTHE NAME\n\n YOU ARE SAVING\n\nIS TOO SHORT\n", preferredStyle: .alert)
                 TooShort.view.tintColor = #colorLiteral(red: 0.5818830132, green: 0.2156915367, blue: 1, alpha: 1)
                 TooShort.view.layer.cornerRadius = 15
                 TooShort.view.layer.borderWidth = 5
                 TooShort.view.layer.borderColor = #colorLiteral(red: 1, green: 0.1491314173, blue: 0, alpha: 1)
            
                 func okHandler(alert: UIAlertAction!)
                 {
                     // Do something if you feel like it
                 }
                 self.present(TooShort, animated: true, completion: nil)
            
                 TooShort.addAction(UIAlertAction(title: "OK", style: .default, handler: okHandler))
             }
             else
             {
                 //DON'T DO WHAT I DO, DO SOMETHING EQUALLLY AWESOME
            
                 doingSomethingAwesome()
            
                 DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500), execute:
                 {
                     self.textFieldField.text = .none
                     self.textFieldView.isHidden = true
                 })
             }
         }
    
         func doingSomethingAwesome()
         {
             let saved = UIAlertController(title: "SAVED", message: "\n\nYOU HAVE\n\nSAVED THE NAME\n\n", preferredStyle: .alert)
             saved.view.tintColor = #colorLiteral(red: 0.01680417731, green: 0.1983509958, blue: 1, alpha: 1)
             saved.view.layer.cornerRadius = 15
             saved.view.layer.borderWidth = 5
             saved.view.layer.borderColor = #colorLiteral(red: 0, green: 0.9768045545, blue: 0, alpha: 1)
        
             func okHandler(alert: UIAlertAction!)
             {
                ...
             }
             self.present(saved, animated: true, completion: nil)
        
             saved.addAction(UIAlertAction(title: "OK", style: .default, handler: okHandler))
          }
    
    
          override func viewDidLoad() {
           super.viewDidLoad()
    
           createYourButton()
    
       }
    }
    

    // Actually took me 30 mins to post this, so if I've missed something, let me know✌️

    // Because I have a scrollView, I figured this was next best thing to disabling it while that view was showing

    func scrollViewWillBeginDragging(_ scrollView: UIScrollView)
    {
        textFieldView.isHidden = true
    }