2016-10-02 1 views
0

Я использую UIAlertController для запроса пользователя ввести строку, и эта строка не должна быть пустой. Для этого я добавляю обработчик для каждого события редактирования в UITextField, расположенном на UIAlertController. Этот обработчик проверяет, если текстовый фильтр пуст, он отключает кнопку «ОК» (находится на UIAlertController), и если текстовый фильтр не пуст, он активирует кнопку «ОК». Кнопка «OK» также расположена на UIAlertController. У меня есть проблемы с доступом к кнопке «OK» от этой функции обработчика:Как получить доступ к кнопке, размещенной на UIAlertController, из обработчика UITextField, размещенного на UIAlertController?

  1. Там нет возможности передать кнопку в качестве параметра непосредственно к функции обработчика, потому что я звоню его с помощью #selector ,
  2. Я также пытался получить доступ к UIAlertController через UITextField.superview из функции обработчика, но это не сработало: он вернул UIView, который не может быть отключен до UIAlertController. И непонятно, почему это так: UITextField является подпрограммой UIAlertController, и поэтому UITextField.superview должен возвращать UIAlertController.
  3. Я также пробовал самый простой способ: объявить UIAlertController как свойство в моем классе ViewController: это позволяет мне получить доступ к кнопке из функции обработчика, не передавая ее непосредственно функции. Но в этом случае я столкнулся с другой проблемой: во время выполнения Xcode показывает это предупреждение в области отладки: попытка загрузить представление контроллера представления при его освобождении не допускается и может привести к неопределенному поведению()

И мой вопрос: как получить доступ к кнопке «ОК» из моей функции обработчика?

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

Почему бы вам не сделать атрибут 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.

+0

Я новичок в Swift и Xcode, и, прежде чем задавать свой вопрос, я подумал, что это грубый способ объявить как класс attrubute UIAlertController или его subviews, и я подумал, что этот способ не соответствует рекомендациям Apple или что-то вроде этого :) Но теперь, когда вы сказали, что это правильный путь, я спокоен. –

+1

Совершенно нормально иметь несколько атрибутов в классе. Как только объект требуется более чем в одной функции, вы должны начать думать о создании атрибутов, а не просто передавать объекты вокруг как параметры. – ezcoding

0

Также я нашел другое решение этой проблемы: достаточно, чтобы сделать ленивую декларацию enterNameAC, чтобы избежать предупреждающих сообщений в отладочной области во время выполнения:

lazy var enterNameAC = UIAlertController() 

Но это не все: Все, что я сказал, что это было около Swift 2, но вчера я обновился до Swift 3, и это чудо: оно работает без сообщений об отладочной области, даже без ленивого объявления!