導致問題的html代碼是這一句:<input type = "file" name = "file"> 調用app的UIDocumentMenuViewController控制
問題發生場景:VC presentViewController 顯示 webVC;
或者VC presentViewController 顯示NVC,webVC在NVC上
這時候在H5上的? input type = "file" 觸發后會導致UIDocumentMenuViewController 和 pre出來的VC(顯示webVC的界面)兩個直接dismis掉,
控制臺會打印這么句警告: ?Warning: Attempt to present <UIImagePickerController: 0x1018a0600> on <XXController: 0x100506020> whose view is not in the window hierarchy!?
個人覺得這是apple的一個bug,應該有開發者反饋了才對,但是到目前WKWebView, UIWebView還存在這個問題,具體原因不曉得,坐等apple修復,在這之前可以參考我的處理方式,把那demo里的UIViewController+Dismis_FileUploadPanel ?.h和.m文件拖到項目里就ok了,不需要額外代碼。修復處理邏輯看下文:
經過分析,發現是WKFileUploadPanel(或 UIWebFileUploadPanel)這么個東西的 _dismisDisplayAnimated: 方法執行的,直接代碼是在UIDocumentMenuViewController控制器關閉后的completion內觸發。
分析后發現 UIDocumentMenuViewController 和 webVC 之間并沒有什么關系(pre關系),只是和WKFileUploadPanel(或 UIWebFileUploadPanel) 這貨有關系(delegate關系),基于這一點結合runtime切入,在presentViewController:animated: 時候對特殊UIDocumentMenuViewController進行標記,
由于cancel是由UIDocumentMenuViewController發起的,所以也對其進行標記。
然后dismissViewControllerAnimated:animated:時候的completion對標記對象進行區分處理,由于兩次dismis是兩個無關的vc順序執行,所以用一個靜態變量dismisFromFileUploadPanel 來標記是否是UIDocumentMenuViewController之后的dismis。
標記的目的是其它正常的dismis可以正確執行,避免其它bug出現。
更新:新增選擇圖片攔截,可知道選擇的圖片信息,修復選擇圖片攔截bug
分析發現圖片文件選擇走的是UIImagePickerController,而UIImagePickerController是通過代理返回結果集,那么在FileUploadPanel內部就必然有回調方法,否則無法完成圖片獲取操作
之前嘗試runtime對WKFileUploadPanel 或 UIWebFileUploadPanel 采用方法替換攔截測試不可行,
新的攔截思路采用代理攔截器實現,在UIImagePickerController setDelegate:時候增加_UIImagePickerController_IFUP 攔截[imagePickerController: didFinishPickingMediaWithInfo:]代理事件
具體實現看demo:https://github.com/youlianchun/WebView_FileUploadBug