使用SwiftUI文本框和WKWebView文本框时应用程序崩溃。

3

我目前有一个应用程序,它在一个网站的文本框(比如搜索框)上方使用了一个SwiftUI文本框。该应用程序在iOS或iPadOS中不会崩溃。

然而,在M1 Mac上的Mac Catalyst中,当我点击SwiftUI文本框然后点击网站上的搜索框时,应用程序立即崩溃。

我创建了一个可重现的示例,如下所示(在XCode 13.2.1中运行)

要重现此崩溃:

  1. 在Mac上启动应用程序(最好是M1)
  2. 点击文本框
  3. 点击Google搜索栏
  4. 应该发生崩溃

在通过Rosetta运行时,崩溃也会发生在日志中,但应用程序不终止。

有人知道问题是什么以及如何修复吗?提前感谢您。

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

以下是关于XCode的错误信息: libc++abi: 终止,未捕获到 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 以下是我的崩溃跟踪:
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
3个回答

4

我在使用maccatalyst的WKWebView时也遇到了同样的崩溃问题。尝试了不同的解决方案后,最终我添加了这段代码以修复我的崩溃问题。

    typealias winClosureType =  @convention(c) (Any, Selector) -> UITextAutocorrectionType
static 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)
    }
}

这里我正在更改UITextInputTraits的autocorrectionType属性。我默认禁用所有文本字段的自动更正功能。如果需要任何文本字段启用自动更正功能,我们必须明确启用autocorrectionType属性。

我们可以将此函数放在AppDelegate类中,然后从此委托函数调用它,如下所示。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{
AppDelegate.swizzleInputTraits()
}

1

我不确定罪魁祸首是什么,可能是MacCatalyst本身,但答案就是在textfield上禁用自动更正。

原因是运行MacCatalyst应用程序假定有一个带有TextField的虚拟键盘,因此这些错误经常出现在生产代码中。由于某种原因,这会导致M1设备崩溃。禁用预测文本是解决此问题的方法。以下是代码:

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

0

我通过交换私有方法-[NSWindow _reallySetFrame:]并手动更正错误的输入来解决了这个崩溃问题。到目前为止,我还没有发现任何副作用。

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

注意:这不是解决方法的完整源代码(您需要添加代码来交换私有的NSWindow方法)。如果您不熟悉“方法交换”,请在互联网上搜索相关内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接