2016-10-02 45 views
0

我使用UIAlertController詢問用戶輸入字符串,並且此字符串不應該爲空。爲此,我爲位於UIAlertController上的UITextField上的每個編輯事件添加處理程序。該處理程序檢查textField是否爲空,它會禁用「OK」按鈕(位於UIAlertController上),如果textField不爲空,它將使「OK」按鈕啓用。 «確定»按鈕也位於UIAlertController上。 我有一個問題,從這個 處理函數訪問«OK»按鈕:如何從放置在UIAlertController上的UITextField的處理程序訪問放置在UIAlertController上的按鈕?

  1. 沒有機會直接通過按鈕作爲參數傳遞給處理函數,因爲我使用#selector叫它。
  2. 我也嘗試通過處理函數的UITextField.superview來訪問UIAlertController,但它不起作用:它返回的UIView不能被降級到UIAlertController。目前尚不清楚它爲什麼如此:UITextField是UIAlertController的子視圖,因此UITextField.superview必須返回UIAlertController。
  3. 我也嘗試了最簡單的方法:在我的ViewController類中聲明UIAlertController屬性:這允許我從處理函數訪問按鈕而不直接將其傳遞給函數。但是在這種情況下,我遇到了另一個問題:在運行時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或其子視圖,我認爲這種方式不符合Apple的建議或像這樣的東西:)但現在,當你說這是正確的方式,我對此冷靜。 –

+1

在班級中擁有多個屬性是很正常的。只要一個對象被多個函數需要,就應該開始考慮創建屬性,而不是一直傳遞對象作爲參數。 – ezcoding

0

而且我發現這個問題的另一種解決方案:它足以讓enterNameAC懶聲明,以避免在調試區域報警消息在運行時:

lazy var enterNameAC = UIAlertController() 

但是,這還不是全部:我說的是關於Swift 2,但昨天我更新爲Swift 3,這真是個奇蹟:它沒有任何調試區域消息,即使沒有懶惰的聲明也能正常工作!

相關問題