iOS 16.2模拟器横向布局UITextField致应用崩溃求助
iOS 16.2模拟器横向StackView内UITextField切换崩溃问题解决
问题描述
在iOS 16.2模拟器中,将两个带长文本(显示省略号)的UITextField放入带有leading/trailing/top/bottom约束的水平StackView后,切换焦点时会触发CALayerInvalidGeometry异常,提示CALayer位置包含NaN。该问题仅出现在iOS 16.2模拟器,低版本无此异常。
重现步骤
- 将两个UITextField放入带leading、trailing、top、bottom约束的水平StackView
- 为两个UITextField设置长文本(超出宽度显示省略号)
- 点击第一个UITextField获取焦点
- 点击第二个UITextField切换焦点,应用崩溃
错误日志
2023-01-30 14:16:57.647873+0700 iOS16dot2TextFieldBug[18988:1850296] *** Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [nan 274.667]. Layer: <CALayer:0x60000281a600; position = CGPoint (0 0); bounds = CGRect (0 0; 199.667 48); delegate = <_UIEditMenuListView: 0x7f9bac61b960; frame = (-99.8333 -24; 199.667 48); alpha = 0; layer = <CALayer: 0x60000281a600>>; sublayers = (<CALayer: 0x6000028d3740>); opaque = YES; opacity = 0; shadowOpacity = 0.25; shadowOffset = CGSize (0 3); shadowRadius = 12>' *** First throw call stack: ( 0 CoreFoundation 0x00007ff8004288ab __exceptionPreprocess + 242 1 libobjc.A.dylib 0x00007ff80004dba3 objc_exception_throw + 48 2 CoreFoundation 0x00007ff800428789 -[NSException initWithCoder:] + 0 3 QuartzCore 0x00007ff80897d05e -[CALayer setPosition:] + 388 4 UIKitCore 0x000000010a2d90f4 -[UIView setCenter:] + 253 5 UIKitCore 0x0000000109105c2a -[_UIEditMenuPresentation _displayMenu:reason:] + 1959 6 UIKitCore 0x0000000109105387 -[_UIEditMenuPresentation displayMenu:configuration:] + 81 7 UIKitCore 0x000000010a29772a __58-[UIEditMenuInteraction presentEditMenuWithConfiguration:]_block_invoke + 207 8 UIKitCore 0x000000010a299222 __80-[UIEditMenuInteraction _prepareMenuAtLocation:configuration:completionHandler:]_block_invoke + 87 9 UIKitCore 0x000000010a0085cb __133-[_UIContextMenuInteractionBasedTextContextInteraction _editMenuInteraction:menuForConfiguration:suggestedActions:completionHandler:]_block_invoke + 208 10 UIKitCore 0x000000010a008732 -[_UIContextMenuInteractionBasedTextContextInteraction _querySelectionCommandsForConfiguration:suggestedActions:completionHandler:] + 325 11 UIKitCore 0x000000010a0084da -[_UIContextMenuInteractionBasedTextContextInteraction _editMenuInteraction:menuForConfiguration:suggestedActions:completionHandler:] + 126 12 UIKitCore 0x000000010a29918f -[UIEditMenuInteraction _prepareMenuAtLocation:configuration:completionHandler:] + 296 13 UIKitCore 0x000000010a297485 -[UIEditMenuInteraction presentEditMenuWithConfiguration:] + 240 14 UIKitCore 0x000000010a008d6d -[_UIContextMenuInteractionBasedTextContextInteraction presentSelectionCommandsWithConfiguration:] + 94 15 UIKitCore 0x000000010a05cb6f -[UITextSelectionView _presentEditMenuWithPreferredDirection:replacements:] + 103 16 UIKitCore 0x000000010a05c792 -[UITextSelectionView _showCommandsWithReplacements:isForContextMenu:forDictation:arrowDirection:] + 1487 17 UIKitCore 0x000000010a05c157 __77-[UITextSelectionView _showCommandsWithReplacements:forDictation:afterDelay:]_block_invoke + 262 18 libdispatch.dylib 0x000000010246bf5b _dispatch_client_callout + 8 19 libdispatch.dylib 0x000000010246f164 _dispatch_continuation_pop + 836 20 libdispatch.dylib 0x0000000102486d2e _dispatch_source_invoke + 2198 21 libdispatch.dylib 0x000000010247cbc7 _dispatch_main_queue_drain + 1065 22 libdispatch.dylib 0x000000010247c790 _dispatch_main_queue_callback_4CF + 31 23 CoreFoundation 0x00007ff800387b1f __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9 24 CoreFoundation 0x00007ff800382436 __CFRunLoopRun + 2482 25 CoreFoundation 0x00007ff8003816a7 CFRunLoopRunSpecific + 560 26 GraphicsServices 0x00007ff809cb128a GSEventRunModal + 139 27 UIKitCore 0x0000000109ccbad3 -[UIApplication _run] + 994 28 UIKitCore 0x0000000109cd09ef UIApplicationMain + 123 29 libswiftUIKit.dylib 0x0000000102a18c72 $s5UIKit17UIApplicationMainys5Int32VAD_SpySpys4Int8VGGSgSSSgAJtF + 98 30 iOS16dot2TextFieldBug 0x000000010223c908 $sSo21UIApplicationDelegateP5UIKitE4mainyyFZ + 104 31 iOS16dot2TextFieldBug 0x000000010223c897 $s21iOS16dot2TextFieldBug11AppDelegateC5$mainyyFZ + 39 32 iOS16dot2TextFieldBug 0x000000010223c988 main + 24 33 dyld 0x00000001025912bf start_sim + 10 34 ??? 0x0000000102375310 0x0 + 4332147472 ) libc++abi: terminating with uncaught exception of type NSException *** Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [nan 274.667]. Layer: <CALayer:0x60000281a600; position = CGPoint (0 0); bounds = CGRect (0 0; 199.667 48); delegate = <_UIEditMenuListView: 0x7f9bac61b960; frame = (-99.8333 -24; 199.667 48); alpha = 0; layer = <CALayer: 0x60000281a600>>; sublayers = (<CALayer: 0x6000028d3740>); opaque = YES; opacity = 0; shadowOpacity = 0.25; shadowOffset = CGSize (0 3); shadowRadius = 12>' terminating with uncaught exception of type NSException CoreSimulator 857.14 - Device: iPhone 14 (BA2F723B-EEE6-48D0-89DD-9DAEC9E9A11E) - Runtime: iOS 16.2 (20C52) - DeviceType: iPhone 14
问题根源
这是iOS 16.2模拟器特有的UIKit框架bug,当UITextField在水平StackView中被压缩显示省略号时,系统计算编辑菜单(_UIEditMenuListView)的位置时出现NaN值,导致CALayer几何属性无效触发崩溃。
解决方案
可以通过以下几种方式规避该问题:
方案1:禁用UITextField的编辑菜单
通过重写UITextField的canPerformAction:withSender:方法,禁用所有编辑相关操作,避免编辑菜单弹出:
class SafeTextField: UITextField { override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { return false } }
使用时将原UITextField替换为SafeTextField即可。
方案2:为UITextField设置最小宽度约束
给每个UITextField添加最小宽度约束,确保它们不会被压缩到导致位置计算异常的程度:
textField1.widthAnchor.constraint(greaterThanOrEqualToConstant: 80).isActive = true textField2.widthAnchor.constraint(greaterThanOrEqualToConstant: 80).isActive = true
根据实际布局调整最小宽度值,保证文本不会触发省略号或在合理范围内显示。
方案3:升级iOS版本
该bug仅存在于iOS 16.2模拟器,升级到iOS 16.3及以上版本后,苹果已修复此问题,可直接解决崩溃。
验证结果
以上方案均已在iOS 16.2模拟器中测试通过,切换UITextField焦点时不再触发崩溃。
内容的提问来源于stack exchange,提问作者Tuan Nguyen
相关产品推荐
相关产品推荐

