16

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);

制約が台無しになっていることを知らせる楽しいクラッシュが発生します。このコードは、8.3 未満では警告なしで正常に動作します。このコード以外に何も入っていないクリーンなプロジェクトでもクラッシュします - プロジェクトは iPad の分割ビュー プロジェクトである必要があります。

以下は、完全なスタック トレースと、テキスト フィールドを 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
4

12 に答える 12

13

編集:この修正は、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"
}

Psコード例の補足として、Swiftでは、;すべての行の最後で使用する必要はありませんが、使用しても問題ありません。


Xcode 7 でビルド

Xcode 7 を使用してアプリをビルドすると、Apple が問題を修正したようです。上記の方法を使用すると、iOS 9 ではテキスト フィールドが表示されなくなります (iOS 8 では正しく表示されますが)。

以下は、コードのスニペットです。これは本来あるべき姿であり、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 でテスト済み

于 2015-04-16T16:56:38.577 に答える
6

-addTextFieldWithConfigurationHandler:このバグは、 ( )を呼び出したときに UIAlertController のビューが読み込まれた場合に発生します[alert isViewLoaded] == YES

-addTextFieldWithConfigurationHandler を呼び出す前にアクセスalert.viewしている場合は、何をしていてもalert.viewへの呼び出しの後に移動し-addTextFieldWithConfigurationHandler:ます。

于 2015-04-24T19:43:27.557 に答える
4

@Dexが述べたように、テキストフィールドを追加した後にコントローラーのビューを変更することでこれを修正しました。ビューの色合いを変更していました。

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

これをテキストフィールドを追加する「後」に移動すると、修正されました。受け入れられた回答とその他の提案により、他のバグが発生しました。申し訳ありませんが、@Dexの回答にまだコメントを投稿する担当者がいません。

于 2015-06-11T23:23:19.970 に答える
3

これは、@BigShay によって回避されたように、UIAlertController のビューのスタイル設定と関係があるようです。

私の例では、UITextField を追加する前にビューの tintColor を設定し、iOS 8 でクラッシュしました。アラートを表示した後に UITextField を追加する @Baza207 によって提供された回避策は、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)
于 2016-03-18T19:16:52.133 に答える
2

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];
}
于 2015-04-11T22:34:59.747 に答える
0

alert.view.frame を明示的に小さいものに設定してみてください。デフォルトでは、アプリケーションビューと同じくらいの大きさで、サブビューでこれをトリガーすると思います。

于 2015-04-11T00:07:55.437 に答える
0

あはは、これは別のスレッドで jcesarmobile によって回答される可能性があると思います: iOS 8 での UIAlertController/UIAlertView scrolling

UIAlertController の長いテキストに関する以前のバグに対処するために多くの人が追加した回避策により、8.3 でこのクラッシュが発生します。また、長いテキストの問題は 8.3 で修正されているため、8.3 でこれを回避するために回避策を条件付きにすることができます。

于 2015-04-13T22:04:15.977 に答える
0

これはすぐに修正されました(私にとって)。Chris が説明したのとまったく同じエラーが発生しました。

NSInteralInconsistencyException - UIKeyboardLayoutAlignmentView

答えは、UIAlertController を提示するときに、animate が「NO」に設定されていることを確認することだけでした。

[self presentViewController:alert animated:NO completion:nil];
于 2015-04-17T00:30:45.927 に答える
0

私が見た解決策が本当に気に入らなかったので、より簡単な解決策を思いつきました。クラッシュは、キーボードが表示され、入力フィールドを含むアラートが表示されたときに (少なくとも私にとっては) 発生します。

アラートを表示する前にキーボードを閉じるだけで、すべて問題ありません。

于 2015-08-24T04:34:06.663 に答える