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
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.
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.
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