Search code examples
swiftuiviewcontrolleruitextfielduialertcontrollercompletion

How can I output UIAlertController to a separate file and output data from there?


I'm trying to output alert to a separate function, since there will be many similar ones.

Here is my alert:

extension UIViewController {
    func alertEditSum(nameCell: String, completion: (() -> Void)) {
        let alertController = UIAlertController(title: "Hello", message: "", preferredStyle: .alert)
        
        
        alertController.addAction(UIAlertAction(title: "Save", style: .default , handler: { _ in
            let nameFolderField = alertController.textFields![0] as UITextField
            if nameFolderField.isTextFieldCheck(text: nameFolderField.text!) == true {
                
                // -----here----
                
            }
        }))
        
        alertController.addAction(UIAlertAction(title: "Cancel"
                                                
                                                , style: .cancel, handler: nil))
        
        alertController.addTextField(configurationHandler: { (nameField: UITextField!) -> Void in
            nameField.clearButtonMode = .always
            nameField.keyboardType = .decimalPad
            
        })
        
        self.present(alertController, animated: true)
        
    }
    
}

and my piece of code is in another VC:

self.sortedDate[indexPath.section-1].personPayment = Double(nameFolderField.text!)!
 do {
try! self.context.save()
collectionView.reloadData()
}

The problem is that I need to consider what exactly the user enters in UITextField. text! (nameFolderField.text!). I also can't add completion to the alert code, writes an error.

Completion should be added to the line where it says: / / - - - - - here----

Please tell me how to solve this problem?


Solution

  • This should do the trick:

    func alertEditSum(nameCell: String, completion: @escaping ((String?) -> Void)) {
    
        let alertController = UIAlertController(title: "Hello", message: "", preferredStyle: .alert)
    
        alertController.addAction(UIAlertAction(title: "Save", style: .default, handler: { _ in
            let nameFolderField = alertController.textFields![0] as UITextField
            if nameFolderField.isTextFieldCheck(text: nameFolderField.text!) == true {
                completion(nameFolderField.text)
            }
        }))
    
        alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in
            completion(nil)
        }))
    
        alertController.addTextField(configurationHandler: { nameField in
            nameField.clearButtonMode = .always
            nameField.keyboardType = .decimalPad
        })
    
        self.present(alertController, animated: true)
    }
    

    To call it:

    theViewController.alertEditSum(nameCell: "text") { text in
        if let text = text {
            //Do stuff
        } else { //Text is invalid or user has cancel
    
        }
    }
    

    Now, isTextFieldCheck(text:) is I guess a method on UITextField, since it's checking its own text, why giving it as a parameter?
    Why not just func isTextValid()?

    I would also avoid the force unwrap: !.

    Going further, would be to use Result<String, Error> in the completion: completion((Result<String, Error>) -> Void)) to have more infos if needed (user has canceled, text wasn't not valid for any reason, etc.)