iOS 8.3 UIAlertController crashes when trying to add a textfield

后端 未结 12 1597
暗喜
暗喜 2020-12-30 03:44

I have an iPad app. I am creating an UIAlertController and adding a textfield. It crashes. It only crashes when I add a textfield.

let alert = UIAlertContr         


        
12条回答
  •  無奈伤痛
    2020-12-30 04:25

    I have the same problem with the new iOS 8.3 and Swift 1.2. UIAlertController in UIViewController with nested UITableView does not work as in start topic.

    So, I made a real modal form.

    1. Create new UIViewController width, set views background to black with 0.4 opacity
    2. Add a 300x150 UIView with two buttons, label and UITextField
    3. Add constraints and other needed staff You must see something like this
    4. Connect modally other controllers with the new one enter image description here
    5. And specify special class for new controller as "PopupWindow". Then create this class:

      import UIKit
      
      class PopupWindow: UIViewController, UITextFieldDelegate {
      
          @IBOutlet var wrapper: UIView!
          @IBOutlet var btnCancel: UIButton!
          @IBOutlet var btnSave: UIButton!
          @IBOutlet var textField: UITextField!
          @IBOutlet var labelField: UILabel!
      
          var keyboardHeight: CGFloat = 0
          var data = [:]
          var closure: ((textField: UITextField!) -> Void)?
          var tmpText = ""
      
          override func viewDidLoad() {
              super.viewDidLoad()
      
              self.labelField.text = self.data["title"] as? String
              self.textField.text = self.data["text"] as? String
      
              self.btnCancel.setTitle("cancel", forState: UIControlState.Normal)
              var tmp = self.data["save"] != nil
                  ? self.data["save"] as! String
                  : "save"
              self.btnSave.setTitle(tmp, forState: UIControlState.Normal)
              self.btnSave.enabled = false
      
              self.wrapper.layer.cornerRadius = 5.0 as CGFloat
              self.textField.becomeFirstResponder()
          }
      
          @IBAction func onBtnCancel() {
              self.dismissViewControllerAnimated(true, completion: nil)
          }
      
          @IBAction func onBtnSave() {
              if self.closure != nil {
                  self.dismissViewControllerAnimated(true, completion: {
                      _ in
                      self.closure!(textField: self.textField)
                  })
              }
      
          }
      
          override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
              self.fixTopOffset()
          }
      
          override func viewWillAppear(animated: Bool) {
              super.viewWillAppear(animated)
      
              NSNotificationCenter.defaultCenter().addObserver(self, selector: "textFieldDidChange:", name: UITextFieldTextDidChangeNotification, object: self.textField)
      
              NSNotificationCenter.defaultCenter().addObserver(self, selector: "onKeyboadWillShow:", name: UIKeyboardWillShowNotification, object: nil)
              NSNotificationCenter.defaultCenter().addObserver(self, selector: "onKeyboadWillShow:", name: UIKeyboardWillChangeFrameNotification, object: nil)
              NSNotificationCenter.defaultCenter().addObserver(self, selector: "onKeyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
          }
      
          override func viewWillDisappear(animated: Bool) {
              super.viewWillDisappear(animated)
      
              NSNotificationCenter.defaultCenter().removeObserver(self, name: UITextFieldTextDidChangeNotification, object: nil)
      
              NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
              NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillChangeFrameNotification, object: nil)
              NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
          }
      
          func onKeyboadWillShow(notification: NSNotification) {
              self.fixTopOffset()
              let info: NSDictionary = notification.userInfo!
              if let rectValue = info[UIKeyboardFrameBeginUserInfoKey] as? NSValue {
                  let kbSize: CGRect = rectValue.CGRectValue()
                  if self.keyboardHeight != kbSize.size.height {
                      self.keyboardHeight = kbSize.size.height
                      self.fixTopOffset()
                  }
              }
          }
      
          func onKeyboardWillHide(notification: NSNotification) {
              self.fixTopOffset()
              if self.keyboardHeight != 0 {
                  self.keyboardHeight = 0
                  self.fixTopOffset()
              }
          }
      
          func fixTopOffset(landscape: Bool = true) {
              let height1: CGFloat = self.view.frame.height / 2
              let height2: CGFloat = height1 - self.keyboardHeight / 2
              let margin: CGFloat = height1 - height2
              for tmp in self.view.constraints() {
                  if let constraint = tmp as? NSLayoutConstraint {
                      if constraint.firstAttribute == NSLayoutAttribute.CenterY {
                          if constraint.constant != margin {
                              constraint.constant = margin
                          }
                      }
                  }
      
              }
          }
      
          func textFieldDidChange(notification: NSNotification) {
              if notification.object != nil {
                  if let textField = notification.object as? UITextField {
                      self.btnSave.enabled = textField.text != self.tmpText
                  }
              }
          }
      
      }
      

    You need to connect all IBOutlets with corresponding elements in view by Ctrl+Drag.

    1. And now you can use it window in any connected controller. For example:

      import UIKit
      
      class ExampleView: UIViewController {
      
          override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {       
              if segue.identifier == "showPopup" {
                  if let controller = segue.destinationViewController as? PopupWindow {
                      controller.data = sender as! NSDictionary
                      // This action will be called after form submission
                      // We just print text in console
                      controller.closure = {
                          (textField: UITextField!) in
                          println(textField)
                      }
                  }
              }
          }
      
          func showPopupWindow() {
              let data = [
                      "title": "My Window",
                      "save": "Save",
                      "text": "Do you realy want to save this text?",
              ]
              self.performSegueWithIdentifier("showPopup", sender: data)
          }
      }
      

    Now I can just add a segue to controller and write any closure in prepareSegue method - and it works!

    I made short video with popup window in my app - http://youtu.be/JmqAAeUN-XU

提交回复
热议问题