简体   繁体   English

使用 swiftUI 文本字段和 WKWebView 文本字段时应用程序崩溃

[英]App crashes when using a swiftUI textfield and a WKWebView textfield

I currently have an app which uses a SwiftUI textfield above a Website's text field (let's say a search box).我目前有一个应用程序,它使用网站文本字段上方的 SwiftUI 文本字段(比如说搜索框)。 The app doesn't crash in iOS or iPadOS.该应用程序不会在 iOS 或 iPadOS 中崩溃。

However, in MacCatalyst on an M1 mac, the app instantly crashes when I click the SwiftUI text field then click the search bar on the website.但是,在 M1 mac 上的 MacCatalyst 中,当我单击 SwiftUI 文本字段然后单击网站上的搜索栏时,应用程序会立即崩溃。

I created a reproducible example that's attached below (ran in XCode 13.2.1)我创建了一个附在下面的可重现示例(在 XCode 13.2.1 中运行)

To reproduce the crash:要重现崩溃:

  1. Launch the app on a mac (preferably M1)在 Mac 上启动应用程序(最好是 M1)
  2. Click in the textfield在文本字段中单击
  3. Click on the google search bar点击谷歌搜索栏
  4. The crash should occur崩溃应该发生

The crash also occurs in the logs when running on Rosetta, but the app doesn't terminate.在 Rosetta 上运行时,日志中也会发生崩溃,但应用程序不会终止。

Does anyone know what the problem is and how I can fix this?有谁知道问题是什么以及我该如何解决? Thank you in advance.先感谢您。

import SwiftUI
import WebKit

struct ContentView: View {
  @State var textObject: String = ""
   
  var body: some View {
    ZStack {
      WebView(url: URL(string: "https://google.com")!)

      TextField("", text: $textObject)
        .background(
          Rectangle()
            .foregroundColor(.black)
        )
    }
  }
}

struct WebView: UIViewRepresentable {   
  var url: URL
 
  func makeUIView(context: Context) -> WKWebView {
    return WKWebView()
  }
 
  func updateUIView(_ webView: WKWebView, context: Context) {
    let request = URLRequest(url: url)
    webView.load(request)
  }
}

Here's the error message from XCode: libc++abi: terminating with uncaught exception of type NSException *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: <SPRoundedWindow: 0x126774250>. "frame=!CGRectIsNull(frame)"' terminating with uncaught exception of type NSException这是来自 XCode 的错误消息: libc++abi: terminating with uncaught exception of type NSException *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: <SPRoundedWindow: 0x126774250>. "frame=!CGRectIsNull(frame)"' terminating with uncaught exception of type NSException libc++abi: terminating with uncaught exception of type NSException *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: <SPRoundedWindow: 0x126774250>. "frame=!CGRectIsNull(frame)"' terminating with uncaught exception of type NSException

My crash trace:我的崩溃痕迹:

0   CoreFoundation                      0x00000001848001cc __exceptionPreprocess + 240
1   libobjc.A.dylib                     0x00000001845517b8 objc_exception_throw + 60
2   Foundation                          0x000000018576e840 -[NSMutableDictionary(NSMutableDictionary) initWithContentsOfFile:] + 0
3   AppKit                              0x0000000187328f20 -[NSWindow _reallySetFrame:] + 904
4   AppKit                              0x00000001873287d8 -[NSWindow _oldPlaceWindow:fromServer:] + 228
5   AppKit                              0x00000001873277f8 -[NSWindow _setFrameCommon:display:fromServer:] + 2200
6   SafariPlatformSupport               0x00000001aac63104 __85-[SPSafariPlatformSupport displayOTPAutoFillRelativeToRect:ofView:completionHandler:]_block_invoke + 300
7   SafariPlatformSupport               0x00000001aac62f8c -[SPSafariPlatformSupport displayOTPAutoFillRelativeToRect:ofView:completionHandler:] + 228
8   UIKitCore                           0x00000001ac7317a0 -[UIKeyboardImpl generateAutofillCandidateByAddingTask:] + 948
9   UIKitCore                           0x00000001ac73b8d0 -[UIKeyboardImpl setDelegate:force:] + 6248
10  UIKitCore                           0x00000001ac41fad4 -[UIKeyboardSceneDelegate _reloadInputViewsForKeyWindowSceneResponder:] + 2080
11  UIKitCore                           0x00000001ac41f288 -[UIKeyboardSceneDelegate _reloadInputViewsForResponder:] + 164
12  UIKitCore                           0x00000001abd918a0 -[UIResponder(UIResponderInputViewAdditions) reloadInputViews] + 132
13  UIKitCore                           0x00000001abd3a298 -[UIResponder becomeFirstResponder] + 856
14  UIKit                               0x0000000202830aa4 -[UITextInputUIResponderAccessibility becomeFirstResponder] + 52
15  UIKitCore                           0x00000001abd6a100 -[UIView(Hierarchy) becomeFirstResponder] + 176
16  WebKit                              0x00000001bd66c5c0 -[WKContentView(WKInteraction) becomeFirstResponderForWebView] + 152
17  WebKit                              0x00000001bd246768 -[WKWebView(WKViewInternalIOS) becomeFirstResponder] + 148
18  WebKit                              0x00000001bd67f88c -[WKContentView(WKInteraction) _elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:] + 1840
19  WebKit                              0x00000001bd381ea0 _ZN6WebKit12WebPageProxy15elementDidFocusERKNS_25FocusedElementInformationEbbN3***9OptionSetIN7WebCore13ActivityState4FlagEEERKNS_8UserDataE + 216
20  WebKit                              0x00000001bd5f66b8 _ZN6WebKit12WebPageProxy17didReceiveMessageERN3IPC10ConnectionERNS1_7DecoderE + 61472
21  WebKit                              0x00000001bcfcc5cc _ZN3IPC18MessageReceiverMap15dispatchMessageERNS_10ConnectionERNS_7DecoderE + 272
22  WebKit                              0x00000001bd35a284 _ZN6WebKit15WebProcessProxy17didReceiveMessageERN3IPC10ConnectionERNS1_7DecoderE + 40
23  WebKit                              0x00000001bcfaeb4c _ZN3IPC10Connection15dispatchMessageENSt3__110unique_ptrINS_7DecoderENS1_14default_deleteIS3_EEEE + 808
24  WebKit                              0x00000001bcfae15c _ZN3IPC10Connection24dispatchIncomingMessagesEv + 508
25  JavaScriptCore                      0x00000001bc5278d0 _ZN3***7RunLoop11performWorkEv + 292
26  JavaScriptCore                      0x00000001bc528a40 _ZN3***7RunLoop11performWorkEPv + 36
27  CoreFoundation                      0x0000000184780c5c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
28  CoreFoundation                      0x0000000184780ba8 __CFRunLoopDoSource0 + 208
29  CoreFoundation                      0x0000000184780894 __CFRunLoopDoSources0 + 268
30  CoreFoundation                      0x000000018477f208 __CFRunLoopRun + 820
31  CoreFoundation                      0x000000018477e734 CFRunLoopRunSpecific + 600
32  HIToolbox                           0x000000018d310f68 RunCurrentEventLoopInMode + 292
33  HIToolbox                           0x000000018d310cdc ReceiveNextEventCommon + 552
34  HIToolbox                           0x000000018d310a9c _BlockUntilNextEventMatchingListInModeWithFilter + 72
35  AppKit                              0x00000001872d4ce0 _DPSNextEvent + 844
36  AppKit                              0x00000001872d3584 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1332
37  AppKit                              0x00000001872c55a4 -[NSApplication run] + 596
38  AppKit                              0x0000000187296c78 NSApplicationMain + 1064
39  AppKit                              0x000000018756d084 +[NSWindow _savedFrameFromString:] + 0
40  UIKitMacHelper                      0x0000000199c7d9ac UINSApplicationMain + 1280
41  UIKitCore                           0x00000001abc0ab28 UIApplicationMain + 164
42  SwiftUI                             0x00000001c0fce8b0 $s7SwiftUI17KitRendererCommon33_ACC2C5639A7D76F611E170E831FCA491LLys5NeverOyXlXpFAESpySpys4Int8VGSgGXEfU_ + 164
43  SwiftUI                             0x00000001c0fce808 $s7SwiftUI6runAppys5NeverOxAA0D0RzlF + 252
44  SwiftUI                             0x00000001c08f54cc $s7SwiftUI3AppPAAE4mainyyFZ + 128
45  TestingGround                       0x000000010056d634 $s13TestingGround0aB3AppV5$mainyyFZ + 40
46  TestingGround                       0x000000010056d6d4 main + 12
47  dyld                                0x00000001015a50f4 start + 520

I'm not sure what is the offender here, probably MacCatalyst itself, but the answer is literally disabling autocorrect on the textfield.我不确定这里的违规者是什么,可能是 MacCatalyst 本身,但答案实际上是在文本字段上禁用自动更正。

The reason is because running MacCatalyst apps assume that there's a virtual keyboard with a TextField, so errors like these appear often in production code.原因是因为运行 MacCatalyst 应用程序假定有一个带有 TextField 的虚拟键盘,因此此类错误经常出现在生产代码中。 For some reason, this causes a crash on M1 devices.出于某种原因,这会导致 M1 设备崩溃。 Disabling predictive text is the solution to this problem.禁用预测文本是解决此问题的方法。 Here's the code:这是代码:

import SwiftUI
import WebKit

struct ContentView: View {
  @State var textObject: String = ""
   
  var body: some View {
    ZStack {
      WebView(url: URL(string: "https://google.com")!)

      TextField("", text: $textObject)
        .background(
          Rectangle()
            .foregroundColor(.black)
        )
        .disableAutoCorrection(true)
    }
  }
}

struct WebView: UIViewRepresentable {   
  var url: URL
 
  func makeUIView(context: Context) -> WKWebView {
    return WKWebView()
  }
 
  func updateUIView(_ webView: WKWebView, context: Context) {
    let request = URLRequest(url: url)
    webView.load(request)
  }
}

I worked around this crash by swizzling the private method -[NSWindow _reallySetFrame:] and manually correct the faulty input.我通过调配私有方法-[NSWindow _reallySetFrame:]并手动更正错误输入来解决此崩溃问题。 I haven't found any side effect of this swizzle so far.到目前为止,我还没有发现这种调酒的任何副作用。

@objc private extension NSWindow {
    
    func kjy_swizzle_reallySetFrame(_ frame: CGRect) {
        var frame = frame
        if frame.isNull {
            frame = .zero
        }
        kjy_swizzle_reallySetFrame(frame)
    }
}

Note: this is not the complete source code for the workaround to work (you need to add code to swizzle the private NSWindow method).注意:这不是解决方法的完整源代码(您需要添加代码来调配私有NSWindow方法)。 If you are not familiar with "method swizzling" please search it on the internet.如果您不熟悉“method swizzling”,请在互联网上搜索。

I also faced the same crash in swift with the WKWebView of maccatalyst.我在使用 maccatalyst 的 WKWebView 的 swift 中也遇到了同样的崩溃。 After trying different solution finally I added this code to fix my crash.最后尝试了不同的解决方案后,我添加了这段代码来修复我的崩溃。

    typealias winClosureType =  @convention(c) (Any, Selector) -> UITextAutocorrectionType
func swizzleInputTraits() {
    guard let textInputTraits: AnyClass = NSClassFromString("UITextInputTraits") else { return }
    let sel_AutocorrectionType: Selector = sel_getUid("autocorrectionType")
    
    if let method = class_getInstanceMethod(textInputTraits, sel_AutocorrectionType) {
        let originalImp: IMP = method_getImplementation(method)
        let original: winClosureType = unsafeBitCast(originalImp, to: winClosureType.self)

        let block : @convention(block) (Any) -> UITextAutocorrectionType = { (textInputTraits) in
            let obj = original(textInputTraits, sel_AutocorrectionType)
            
            return obj == .default ? .no : obj
        }
        let imp: IMP = imp_implementationWithBlock(block)
        method_setImplementation(method, imp)
    }
}

Here i am swizzling the autocorrectionType property of UITextInputTraits.在这里,我正在调整 UITextInputTraits 的 autocorrectionType 属性。 I am disabling the autocorrectionType by default for all the textFields.我默认为所有文本字段禁用自动更正类型。 We have to explicitly enabled autocorrectionType property if needed for any text field.如果任何文本字段需要,我们必须显式启用 autocorrectionType 属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM