如何从位于UIAlertController上的UITextField处理程序访问放置在UIAlertController上的按钮?

时间:2016-10-02 14:25:12

标签: ios swift xcode uikit

我正在使用UIAlertController要求用户输入字符串,并且此字符串不应为空。为此,我在位于UIAlertController上的UITextField上为每个编辑事件添加处理程序。此处理程序检查,如果textField为空,则禁用“OK”按钮(位于UIAlertController上),如果textField不为空,则使“OK”按钮启用。 “OK”按钮也位于UIAlertController上。 我有一个问题,从这里访问«OK»按钮 处理函数:

  1. 没有机会将按钮作为参数直接传递给处理函数,因为我正在使用#selector调用它。
  2. 我也尝试通过处理程序函数的UITextField.superview访问UIAlertController,但它不起作用:它返回了UIView,它无法下载到UIAlertController。并且不清楚为什么会这样:UITextField是UIAlertController的子视图,因此UITextField.superview必须返回UIAlertController。
  3. 我也尝试过最简单的方法:在我的ViewController类中声明UIAlertController作为属性:这允许我从处理函数访问按钮而不直接将其传递给函数。但是在这种情况下我遇到了另一个问题:在运行时Xcode在调试区域显示此警告:不允许在取消分配时尝试加载视图控制器的视图,并且可能导致未定义的行为()
  4. 我的问题是如何从我的处理函数中访问«OK»按钮?

    class TVC_ProgramsList: UITableViewController {
    
        var enterNameAC = UIAlertController()
    
        @IBAction func addpush(sender: UIBarButtonItem) {
            addProgram()
        }
    
        func addProgram() {
    
            enterNameAC = UIAlertController(title: "Adding program", message: "Enter program name", preferredStyle: UIAlertControllerStyle.Alert)
            enterNameAC.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
            enterNameAC.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
            enterNameAC.addTextFieldWithConfigurationHandler { (textField) -> Void in
                textField.placeholder = "Program name"
    
                textField.addTarget(self, action: #selector(TVC_ProgramsList.enterProgramNameAC_editingTextField), forControlEvents: UIControlEvents.AllEditingEvents)
    
            }
    
            self.presentViewController(enterNameAC, animated: true, completion: nil)
    
        }
    
    
        func enterProgramNameAC_editingTextField() {
            let programNameString = enterNameAC.textFields![0].text!
    
            if programNameString.characters.count > 0 {
                enterNameAC.actions[1].enabled = true
            } else {
                enterNameAC.actions[1].enabled = false
            }
        }
    
    }
    

2 个答案:

答案 0 :(得分:2)

为什么不创建UIAlertAction的属性?我已经改变了你的代码:

class TVC_ProgramsList: UITableViewController {

  var enterNameAC = UIAlertController()
  let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)

  @IBAction func addpush(sender: UIBarButtonItem) {
     addProgram()
  }

  func addProgram() {
    enterNameAC = UIAlertController(title: "Adding program", message: "Enter program name", preferredStyle: UIAlertControllerStyle.Alert)
    enterNameAC.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
    enterNameAC.addAction(self.okAction)
    enterNameAC.addTextFieldWithConfigurationHandler { (textField) -> Void in
        textField.placeholder = "Program name"
        textField.addTarget(self, action: #selector(TVC_ProgramsList.enterProgramNameAC_editingTextField), forControlEvents: UIControlEvents.AllEditingEvents)

    }

    self.presentViewController(enterNameAC, animated: true, completion: nil)

  }

  func enterProgramNameAC_editingTextField() {
    let programNameString = enterNameAC.textFields![0].text!
    // use okAction here 
    self.okAction.enabled = programNameString.characters.count > 0
  }
}

无法使用addTarget传递它。但它是一种有效的方法,可以从中创建一个类属性,从而使它可以在ViewController的其他部分中访问。

答案 1 :(得分:0)

此外,我找到了另一个解决此问题的方法:它足以使enterNameAC的延迟声明在运行时避免调试区域中的警报消息:

lazy var enterNameAC = UIAlertController()

但并非全部:所有我说它都是关于 Swift 2 ,但昨天我更新为 Swift 3 ,这是奇迹:它没有任何调试区域消息,即使没有懒惰的声明!