iOS 8.3 UIAlertController 在尝试添加文本字段时崩溃

Posted

技术标签:

【中文标题】iOS 8.3 UIAlertController 在尝试添加文本字段时崩溃【英文标题】:iOS 8.3 UIAlertController crashes when trying to add a textfield 【发布时间】:2015-06-16 18:24:28 【问题描述】:

我有一个 iPad 应用程序。我正在创建一个 UIAlertController 并添加一个文本字段。它崩溃了。它仅在我添加文本字段时崩溃。

let alert = UIAlertController(title: "Enter Name", message:nil, preferredStyle: UIAlertControllerStyle.Alert);         
alert.addTextFieldWithConfigurationHandler  (textfield:UITextField!) -> Void in
                textfield.placeholder = "Sexy time";

            
 alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: (action:UIAlertAction!) -> Void in
      //Some action here   
 ));

 self.presentViewController(alert, animated: true, completion: nil);

我得到一个有趣的崩溃,告诉我约束被搞砸了。此代码在

这是完整的堆栈跟踪以及奇怪的约束警告,仅在尝试将文本字段添加到 alertController 后才会出现。

2015-04-10 15:25:07.155 Observation[18235:281813] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fb66cf9dfc0 UITableView:0x7fb66b855000.left == UIView:0x7fb66fae68e0.left>
    When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2015-04-10 15:25:07.155 Observation[18235:281813] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fb66cf9e010 UITableView:0x7fb66b855000.right == UIView:0x7fb66fae68e0.right>
    When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2015-04-10 15:25:07.155 Observation[18235:281813] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fb66fb37f90 UITableView:0x7fb66b855000.top == UIView:0x7fb66fae68e0.top>
    When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2015-04-10 15:25:07.156 Observation[18235:281813] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fb66fb80580 UITableView:0x7fb66b855000.bottom == UIView:0x7fb66fae68e0.bottom>
    When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2015-04-10 15:25:13.589 Observation[18235:281813] View hierarchy unprepared for constraint.
    Constraint: <NSLayoutConstraint:0x7fb66cf9dfc0 UITableView:0x7fb66b855000.left == UIView:0x7fb66fae68e0.left>
    Container hierarchy: 
<UIView: 0x7fb66fa86e00; frame = (0 0; 0 0); layer = <CALayer: 0x7fb66fadf8e0>>
   | <UIView: 0x7fb66af3e080; frame = (0 0; 0 0); clipsToBounds = YES; layer = <CALayer: 0x7fb66fae32c0>>
   |    | <_UIAlertControllerShadowedScrollView: 0x7fb66fa68c80; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x7fb66fa38a80>; layer = <CALayer: 0x7fb66fa97560>; contentOffset: 0, 0; contentSize: 0, 0>
   |    |    | <UIView: 0x7fb66fa87350; frame = (0 0; 0 0); layer = <CALayer: 0x7fb66fadf810>>
   |    |    |    | <UILabel: 0x7fb66fa88740; frame = (0 0; 0 0); text = 'Enter Name'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fb66fa94ed0>>
   |    |    |    | <UILabel: 0x7fb66fa73710; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fb66cc0ee10>>
   |    |    |    | <UIView: 0x7fb66fae68e0; frame = (0 0; 0 0); clipsToBounds = YES; layer = <CALayer: 0x7fb66fa90160>>
   |    | <UILabel: 0x7fb66fa3ad40; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fb66fa73680>>
   |    | <UICollectionView: 0x7fb66c130200; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x7fb66faebab0>; layer = <CALayer: 0x7fb66fa3acf0>; contentOffset: 0, 0; contentSize: 0, 0> collection view layout: <_UIAlertControllerCollectionViewFlowLayout: 0x7fb66fae0b30>
    View not found in container hierarchy: <UITableView: 0x7fb66b855000; frame = (0 20; 768 1004); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fb66cf79f30>; layer = <CALayer: 0x7fb66cf600a0>; contentOffset: 0, 0; contentSize: 768, 25>
    That view's superview: NO SUPERVIEW
2015-04-10 15:25:13.594 Observation[18235:281813] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view.  Does the constraint reference something from outside the subtree of the view?  That's illegal. constraint:<NSLayoutConstraint:0x7fb66cf9dfc0 UITableView:0x7fb66b855000.left == UIView:0x7fb66fae68e0.left> view:<UIView: 0x7fb66fa86e00; frame = (0 0; 0 0); layer = <CALayer: 0x7fb66fadf8e0>>'
*** First throw call stack:
(
    0   CoreFoundation                      0x0000000102940c65 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010221dbb7 objc_exception_throw + 45
    2   CoreFoundation                      0x0000000102940b9d +[NSException raise:format:] + 205
    3   Foundation                          0x0000000101daf479 -[NSLayoutConstraint _addToEngine:integralizationAdjustment:mutuallyExclusiveConstraints:] + 187
    4   UIKit                               0x00000001039bca34 __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke_2 + 474
    5   Foundation                          0x0000000101dbd1be -[NSISEngine withBehaviors:performModifications:] + 155
    6   UIKit                               0x00000001039bc83a __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke + 452
    7   UIKit                               0x00000001039bc64d -[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:] + 197
    8   UIKit                               0x00000001039bc933 __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke_2 + 217
    9   Foundation                          0x0000000101dbd1be -[NSISEngine withBehaviors:performModifications:] + 155
    10  UIKit                               0x00000001039bc83a __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke + 452
    11  UIKit                               0x00000001039bc64d -[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:] + 197
    12  UIKit                               0x00000001039bc933 __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke_2 + 217
    13  Foundation                          0x0000000101dbd1be -[NSISEngine withBehaviors:performModifications:] + 155
    14  UIKit                               0x00000001039bc83a __57-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:]_block_invoke + 452
    15  UIKit                               0x00000001039bc64d -[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:] + 197
    16  UIKit                               0x00000001033b5717 __40-[UIView(Hierarchy) layoutBelowIfNeeded]_block_invoke + 39
    17  Foundation                          0x0000000101dbd1be -[NSISEngine withBehaviors:performModifications:] + 155
    18  UIKit                               0x00000001033b5556 -[UIView(Hierarchy) layoutBelowIfNeeded] + 320
    19  UIKit                               0x000000010374a394 -[_UIAlertControllerAnimatedTransitioning animateTransition:] + 470
    20  UIKit                               0x000000010344fa4e __56-[UIPresentationController runTransitionForCurrentState]_block_invoke + 1867
    21  UIKit                               0x000000010336562c _applyBlockToCFArrayCopiedToStack + 314
    22  UIKit                               0x00000001033654a6 _afterCACommitHandler + 533
    23  CoreFoundation                      0x0000000102873ca7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
    24  CoreFoundation                      0x0000000102873c00 __CFRunLoopDoObservers + 368
    25  CoreFoundation                      0x0000000102869a33 __CFRunLoopRun + 1123
    26  CoreFoundation                      0x0000000102869366 CFRunLoopRunSpecific + 470
    27  GraphicsServices                    0x0000000106dd6a3e GSEventRunModal + 161
    28  UIKit                               0x0000000103341900 UIApplicationMain + 1282
    29  Observation                         0x0000000101612927 main + 135
    30  libdyld.dylib                       0x0000000104f60145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

【问题讨论】:

仅供参考,该项目是在 iPad 上运行的拆分视图。 我得到同样的错误。在我的情况下,uialertcontroller 是通过 uitableview 的部分标题中的按钮触发的。 【参考方案1】:

编辑:此修复会根据您是使用 Xcode 6 还是 Xcode 7 构建而有所不同,因此我添加了两个 Xcode 版本的相关信息。


我今天遇到了这个问题,它的意思是它不能将文本字段添加到视图控制器的视图中,或者它不能将自动布局约束添加到它的父视图中。这似乎是因为它还没有创建要添加它的超级视图,所以它都发生了恐慌和崩溃。

我发现的简单修复是在您告诉警报控制器呈现后添加文本字段。这对我来说是固定的,但我不确定它是否会影响警报显示时弹出的文本字段之类的任何内容。

使用 Xcode 6 构建

let alertController = UIAlertController(title: "Enter Name", message:nil, preferredStyle: .Alert)

let okAction = UIAlertAction(title: "Ok", style: .Default)  (_) -> Void in
    // Some action here

alertController.addAction(okAction)

presentViewController(alertController, animated: true, completion: nil)

// Add any text fields after presenting the alert controller to fix crash in ios 8.3
alertController.addTextFieldWithConfigurationHandler  (textfield) -> Void in
    textfield.placeholder = "Name"

附:作为代码示例的旁注,请记住使用 Swift,您不需要在每一行的末尾使用 ;,尽管这样做并不重要。 ?


使用 Xcode 7 构建

当您使用 Xcode 7 构建应用时,Apple 似乎已经解决了这个问题。使用上面显示的方法将不再在 iOS 9 中显示文本字段(即使在 iOS 8 中仍能正确显示)。

下面是一段 sn-p 代码,它应该一直是这样的,当它内置在 Xcode 7 中时,它可以在 iOS 8 和 iOS 9 中正确运行。

let alertController = UIAlertController(title: "Enter Name", message:nil, preferredStyle: .Alert)

alertController.addTextFieldWithConfigurationHandler  (textfield) -> Void in
    textfield.placeholder = "Name"


let okAction = UIAlertAction(title: "Ok", style: .Default)  (_) -> Void in
    // Some action here

alertController.addAction(okAction)

presentViewController(alertController, animated: true, completion: nil)

使用 Xcode 7 GM (7A218) 在 Swift 2.0 和 Obj-C 中测试

【讨论】:

太棒了,谢谢,完美运行。是的,我确实知道我不需要使用“;”,如果我不使用它只会感觉不完整:) 此解决方法修复了 iOS 8.3 和 8.4 上的崩溃问题。但是,请注意,从 iOS 9 beta 1 到 3,这会导致警报控制器没有文本字段。因此,此解决方法应仅适用于 iOS 8.x。 我可以确认,在 Xcode 7 Beta 3 中内置的当前 iOS 9 Beta 中,此修复不起作用。正如@junjie 指出的那样,它只是不添加文本字段。 Xcode 7 和 iOS 9 的 GM 版本发布时我会更新答案。【参考方案2】:

如果在调用-addTextFieldWithConfigurationHandler: ([alert isViewLoaded] == YES) 时加载了 UIAlertController 的视图,则会触发此错误。

如果您在调用 -addTextFieldWithConfigurationHandler 之前访问 alert.view,请将您对 alert.view 执行的操作移至调用 -addTextFieldWithConfigurationHandler: 之后。

【讨论】:

【参考方案3】:

正如@Dex 提到的,我通过在添加文本字段后修改控制器的视图来解决此问题。我正在修改视图的色调。

controller.view.tintColor = ...some color...

将其移至添加文本字段的“之后”为我修复了它。接受的答案和其他建议给我带来了其他错误。抱歉,我还没有代表对@Dex 的回答发表评论。

【讨论】:

这是为我解决问题的唯一答案。谢谢! @Dyson,不客气。同样值得注意的是,自从我在 6 月份进行修复以来,这一直是可靠的。 在我的代码中有完全相同的问题。这个解决方案解决它!【参考方案4】:

这似乎与 UIAlertController 的视图样式有关,正如 @BigShay 所避免的那样。

在我的示例中,我在添加 UITextField 之前设置了视图的 tintColor,但我在 iOS 8 中崩溃了。@Baza207 给出的在显示警报后添加 UITextField 的解决方法避免了 iOS 8 中的崩溃,但它也会导致在 iOS 9 中根本没有出现任何文本字段。

如果您只是在添加文本字段之后将样式移动到,它适用于 iOS 8 和 iOS 9(在 iOS 8 中不会崩溃,在 iOS 9 中不会丢失文本字段):

iOS 8 崩溃

适用于 iOS 9

alertController.view.tintColor = UIColor.blueColor()

alertController.addTextFieldWithConfigurationHandler  textField in


presentViewController(alertController, animated: true, completion: nil)

适用于 iOS 8

iOS 9 中没有文本文本字段

alertController.view.tintColor = UIColor.blueColor()

presentViewController(alertController, animated: true, completion: nil)

alertController.addTextFieldWithConfigurationHandler  textField in

适用于 iOS 8

适用于 iOS 9

alertController.addTextFieldWithConfigurationHandler  textField in


alertController.view.tintColor = UIColor.blueColor()

presentViewController(alertController, animated: true, completion: nil)

【讨论】:

【参考方案5】:

iOS 8.3 相关警报中似乎确实存在错误。它在(已弃用的)UIAlertView 和仅限 iOS8 的 UIAlertController 上都出现。当我尝试将文本字段添加到这些控制器中的任何一个时,都会出现以下崩溃:

 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'The layout constraints still need update after sending -updateConstraints to <_UIKeyboardLayoutAlignmentView: 0x792d28e0; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <CALayer: 0x792d2ab0>>.
_UIKeyboardLayoutAlignmentView or one of its superclasses may have overridden -updateConstraints without calling super. Or, something may have dirtied layout constraints in the middle of updating them.  Both are programming errors.'

没有文本字段的警报是可以的,但是显示样式为 UIAlertViewStylePlainTextInput 的 UIAlertView 或显示带有通过 addTextFieldWithConfigurationHandler 添加的文本字段的 UIAlertController 将导致上述崩溃。

修复似乎是在调用 show 之前在 UIAlertController 上设置一个预防性框架。此框架在显示之前被覆盖,但可以防止崩溃。

if (NSClassFromString(@"UIAlertController")) 
    // iOS8
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Alert"
                                                                   message:@"Be alert, not alarmed"
                                                            preferredStyle:UIAlertControllerStyleAlert];
    [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) 
        textField.keyboardType = UIKeyboardTypeEmailAddress;

    ];
    alert.view.frame = CGRectMake(0.0, 0.0, 320.0, 400.0); // Workaround iOS8.3 bug - set this to larger than you'll need

    [self presentViewController:alert animated:YES completion:^
        [alert.textFields[0] becomeFirstResponder];
    ];
 else 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert"
                                                    message:@"Be alert, not alarmed"
                                                   delegate:nil
                                          cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil];
    alert.alertViewStyle = UIAlertViewStylePlainTextInput;
    UITextField *emailField = [alert textFieldAtIndex:0];
    emailField.keyboardType = UIKeyboardTypeEmailAddress;

    [alert show];

【讨论】:

我非常希望这对我有用,但不幸的是它没有 请看下面我的回答,我遇到了同样的崩溃并修复了它。 在此页面上也可以查看我的答案,立即修复。有同样的 NSInternalInconsistencyException 问题。 其他对我有用的方式 - 如果你想继续使用 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" -> 在显示调用之前 [self.view endEditing:YES] ;但是我建议转移到 AlertController【参考方案6】:

我刚刚在我的测试项目中运行了你的代码——在 8.3 上一切正常。

View not found in container hierarchy:

如果您弄乱了 UIViewController 的子/父关系,通常会出现此错误。有几点需要考虑:

您用于显示警报的控制器位于最顶层,并且尚未显示任何其他内容 父控制器要么拥有您小时候使用的控制器 (addChildViewController:),要么处于通过 presentViewController:animated:completion: 或类似方式呈现它的状态 在呈现另一个 ViewController 之前加载控制器的视图

另外,框架肯定有问题。

【讨论】:

我忘了说项目需要是ipad上的splitviewcontroller。当我将代码添加到 xcode 为您创建的默认 DetailViewController 中的 ViewDidAppear 方法时发生【参考方案7】:

我遇到了一个在 cmets 中也提到过的类似问题。 如果你得到,请看这个。

*** 由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'布局约束 发送 -updateConstraints 后仍需要更新 <_uikeyboardlayoutalignmentview:>。 _UIKeyboardLayoutAlignmentView 或其超类之一可能已覆盖 -updateConstraints 而不调用 super。或者,有些东西可能 在更新它们的过程中有脏的布局约束。两个都 是编程错误。'

NSInteralInconsistencyException - UIKeyboardLayoutAlignmentView

【讨论】:

【参考方案8】:

尝试将 alert.view.frame 显式设置为较小的值。我认为默认情况下它可能与应用程序视图一样大,在其子视图上触发。

【讨论】:

【参考方案9】:

啊哈,我认为 jcesarmobile 可能会在另一个线程中回答: UIAlertController/UIAlertView scrolling on iOS 8

许多人添加的解决方法是在 UIAlertController 中处理以前的长文本错误,现在在 8.3 中会导致此崩溃。并且长文本问题在 8.3 中已修复,因此可以在 8.3 中设置有条件的解决方法来避免这种情况

【讨论】:

【参考方案10】:

这立即修复了它(对我来说)。我遇到了与 Chris 描述的完全相同的错误:

NSInteralInconsistencyException - UIKeyboardLayoutAlignmentView

答案只是确保在呈现 UIAlertController 时将动画设置为“否”。

[self presentViewController:alert animated:NO completion:nil];

【讨论】:

当问题是 UIKeyboardLayoutAlignmentView 时这可能会起作用,但如果堆栈跟踪是按照这个问题,当文本字段添加到警报时会发生崩溃,甚至在调用 presentViewController 之前。 Baza 的回答解决了这个问题。 在我的应用程序中这对我不起作用,但我的链接中的修复确实如此。猜猜它是那些奇怪的之一。回复:它为原始问题带来了不同的解决方案,是的,我们知道,但是正如一些人在本主题中询问的那样崩溃。所以最好是链接。 是的,感谢大家为未来的观众阐明这一区别。【参考方案11】:

我真的不喜欢我看到的解决方案并想出了一个更简单的解决方案。当键盘可见并且出现带有输入字段的警报时,就会发生崩溃(至少对我而言)。

我只是在显示警报之前关闭键盘,然后一切都很好。

【讨论】:

【参考方案12】:

我对新的 iOS 8.3 和 Swift 1.2 也有同样的问题。带有嵌套 UITableView 的 UIViewController 中的 UIAlertController 不能像开始主题那样工作。

所以,我做了一个真正的模态表单。

    创建新的 UIViewController 宽度,将视图背景设置为黑色,不透明度为 0.4 添加一个带有两个按钮、标签和 UITextField 的 300x150 UIView 添加约束和其他需要的人员 以模态方式将其他控制器与新控制器连接

    并将新控制器的特殊类指定为“PopupWindow”。然后创建这个类:

    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
                
            
        
    
    
    

您需要通过 Ctrl+Drag 将所有 IBOutlets 与视图中的相应元素连接起来。

    现在您可以在任何连接的控制器中使用它。例如:

    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)
        
    
    

现在我可以向控制器添加一个 segue 并在 prepareSegue 方法中编写任何闭包 - 它可以工作!

我在我的应用中制作了带有弹出窗口的短视频 - http://youtu.be/JmqAAeUN-XU

【讨论】:

重新创建 UIAlertController 似乎是解决此类问题的一种非常冗长的方法。作为一般规则,重新创建应该是最后的手段,如果您想要添加功能,则应该使用子类或扩展。

以上是关于iOS 8.3 UIAlertController 在尝试添加文本字段时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

iOS UIAlertController

iOS 10:UIAlertController 只显示一个动作

为啥 iOS7 中的 UIAlertController 收到 nil 值?

iOS UIAlertController

IOS开发之UIAlertView与UIAlertController的详尽用法说明

iOS - UIAlertController三种显示提示框代码