现象
- iOS13.3设备输入框长按,弹出Menu后点击查询
- 下滑关闭查询页面
- App无法响应交互
问题分析
- App卡死,通过flex还能操作App,故主线程并未阻塞
- 页面用户交互关闭,通过调试页面属性,并未发现
userInteractionEnabled
关闭 - 透明视图拦截交互事件,通过flex发现全屏透明
_UIFallbackPresentationWindow
以上分析可得冻屏原因为_UIFallbackPresentationWindow
作为keyWindow
拦截了用户交互,且该window为全屏、透明,故造成冻屏的现象。
疑问分析
1. _UIFallbackPresentationWindow
为什么不消失?
通过memory graph获取引用关系,该window被Input相关实例持有,猜测是否为业务方对TextFiled或Input等做业务拦截导致,但实验证明纯净输入框也能复现,故根本原因不是某个实例强行持有。
点击查询页中完成
时_UIFallbackPresentationWindow
会触发setHidden
与重设keyWindow
故不会出现冻屏现象,而手势滑动的交互式转场并不会触发setHidden
与重设keyWindow
,故导致keyWindow
被占用,拦截了用户交互。
2. _UIFallbackPresentationWindow
为什么会展现?
通过Hook window的init
与makeKeyWindow
获取使用该window的入口函数。
在堆栈+[_UITextServiceSession showServiceForType:withContext:]
中寻到FallbackPresentation
相关使用。
通过此行代码的地址0x7fff47ba3d35
找到其代码跳转逻辑由+[_UITextServiceSession shouldPresentServiceInSameWindowAsView:]
控制,即该函数返回YES,则在当前window进行页面跳转,若返回NO,则走fallback逻辑,交由_UIFallbackPresentationViewController
控制其转场逻辑,即会展示_UIFallbackPresentationWindow
。
再分析+[_UITextServiceSession shouldPresentServiceInSameWindowAsView:]
其内部实现,主要由_window
、_isTextEffectsWindow
与__UIApplicationLinkedOnVersion
控制逻辑。
经排查_window
与_isTextEffectsWindow
均返回正常,而唯一变化的为__UIApplicationLinkedOnVersion
,该常量属于linker的version标识,和xCode版本强相关(XCode 11.0为0xD0000
,XCode 11.2为0xD0200
)。
获取UIKitCore源码文件/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore
,在Hopper中解析得到,通过arg2
获取window,如果window的_isTextEffectsWindow
属性为YES,则直接返回NO,反之判断XCode版本是否大于或等于11.2版本,若满足返回YES,不满足则返回NO。
总结
iOS13.3系统使用了新特性,同时对linker即编译器的版本进行校验,低于11.2版本的包则走入fallback逻辑,同时fallback逻辑中存在退场不完全的Bug。综上所诉为系统Bug,且可通过升级XCode解决。
网友评论