Lonaso
Lonaso

Reputation: 55

NSInvalidArgumentException: How to check script message handler with name when one already exists?

Whenever View switches to another View, the error says that it is adding script message handler with name "jsHandler" when one already exists? Do I have to check existing name and then add it? How can I check? I find nothing in documentation. I tried with ModalView, too.

Here is ContentView

struct ContentView: View {
    @State var counter: Int = 0

    var body: some View {
        NavigationView{
            WebViewController(filePath: "index.html")
            .navigationBarTitle(Text("Title"))
            .navigationBarItems(trailing:
                NavigationLink(destination: Text("Another View")) {
                    Text("Next")
                }
            )
        }
    }
}

Here is WebViewController.

import SwiftUI
import WebKit

struct WebViewController: UIViewRepresentable {

    let filePath: String

    func makeUIView(context: Context) -> WKWebView  {
        return WKWebView()
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {

        uiView.configuration.userContentController.add(ContentController(), name: "jsHandler")

        let bundleURL = Bundle.main.resourceURL!.absoluteURL
        let html = bundleURL.appendingPathComponent(filePath)
        uiView.loadFileURL(html, allowingReadAccessTo:bundleURL)
    }
    class ContentController: NSObject, WKScriptMessageHandler {
        func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
            if message.name == "jsHandler"{
                print(message.body)
            }
        }
    }
}

Here is Logcat:

    2019-11-16 23:45:41.330209+0630 tut1[33510:959393] Simulator user has requested new graphics quality: 10
2019-11-16 23:45:46.236890+0630 tut1[33510:959393] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to add script message handler with name 'jsHandler' when one already exists.'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff23baa1ee __exceptionPreprocess + 350
    1   libobjc.A.dylib                     0x00007fff50864b20 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff23baa02c +[NSException raise:format:] + 188
    3   WebKit                              0x00007fff2d0c49dd -[WKUserContentController addScriptMessageHandler:name:] + 209
    4   tut1                                0x000000010c36d613 $s4tut117WebViewControllerV12updateUIView_7contextySo05WKWebC0C_7SwiftUI0F20RepresentableContextVyACGtF + 483
    5   tut1                                0x000000010c36de91 $s4tut117WebViewControllerV7SwiftUI19UIViewRepresentableAadEP06updateG0_7contexty0G4TypeQz_AD0gH7ContextVyxGtFTW + 17
    6   SwiftUI                             0x00007fff2c5fc341 $s7SwiftUI32PlatformViewRepresentableAdaptor33_19642D833A8FE469B137699ED1426762LLV06updateD8Provider_7contexty10UIViewTypeQz_AA0cdE7ContextVyADyxGGtF + 289
    7   SwiftUI                             0x00007fff2c2653a7 $s7SwiftUI17PlatformViewChild33_A513612C07DFA438E70B9FA90719B40DLLV6update7contexty14AttributeGraph0O7ContextVyADyxGGz_tFyyXEfU_ + 2343
    8   SwiftUI                             0x00007fff2c25eb86 $s7SwiftUI17PlatformViewChild33_A513612C07DFA438E70B9FA90719B40DLLV6update7contexty14AttributeGraph0O7ContextVyADyxGGz_tF + 310
    9   SwiftUI                             0x00007fff2c2665d0 $s7SwiftUI17PlatformViewChild33_A513612C07DFA438E70B9FA90719B40DLLVyxG14AttributeGraph07UntypedM0AafGP7_update_5graph9attributeySv_So10AGGraphRefaSo11AGAttributeatFZTW + 32
    10  AttributeGraph                      0x00007fff2f8f1849 $sTA + 25
    11  AttributeGraph                      0x00007fff2f8d9255 _ZN2AG5Graph11UpdateStack6updateEv + 1111
    12  AttributeGraph                      0x00007fff2f8d9513 _ZN2AG5Graph16update_attributeEjb + 377
    13  AttributeGraph                      0x00007fff2f8de131 _ZN2AG8Subgraph6updateEj + 929
    14  SwiftUI                             0x00007fff2c10d100 $s7SwiftUI9ViewGraphC14runTransaction33_D63C4EB7F2B205694B6515509E76E98BLL2inySo10AGGraphRefa_tF + 224
    15  SwiftUI                             0x00007fff2c10d517 $s7SwiftUI9ViewGraphC13updateOutputs2atyAA4TimeV_tFSb5prefs_Sb9idealSizeAC0F0V7outputstSo10AGGraphRefaXEfU_ + 103
    16  SwiftUI                             0x00007fff2c10d1d1 $s7SwiftUI9ViewGraphC13updateOutputs2atyAA4TimeV_tF + 145
    17  SwiftUI                             0x00007fff2c4af579 $s7SwiftUI16ViewRendererHostPAAE6render8interval17updateDisplayListySd_SbtFyyXEfU_yyXEfU_ + 1001
    18  SwiftUI                             0x00007fff2c4aef8a $s7SwiftUI16ViewRendererHostPAAE6render8interval17updateDisplayListySd_SbtFyyXEfU_ + 634
    19  SwiftUI                             0x00007fff2c4a4274 $s7SwiftUI16ViewRendererHostPAAE6render8interval17updateDisplayListySd_SbtF + 436
    20  SwiftUI                             0x00007fff2c65a182 $s7SwiftUI14_UIHostingViewC14layoutSubviewsyyF + 226
    21  SwiftUI                             0x00007fff2c65a1a5 $s7SwiftUI14_UIHostingViewC14layoutSubviewsyyFTo + 21
    22  UIKitCore                           0x00007fff47a52ad5 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2478
    23  QuartzCore                          0x00007fff2b06e91d -[CALayer layoutSublayers] + 255
    24  QuartzCore                          0x00007fff2b073323 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 517
    25  QuartzCore                          0x00007fff2b07fa7c _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 80
    26  QuartzCore                          0x00007fff2afc6e54 _ZN2CA7Context18commit_transactionEPNS_11TransactionEd + 324
    27  QuartzCore                          0x00007fff2affc32f _ZN2CA11Transaction6commitEv + 643
    28  SwiftUI                             0x00007fff2c65a2a4 $s7SwiftUI14_UIHostingViewC16displayLinkTimer9timestampyAA4TimeV_tF + 228
    29  SwiftUI                             0x00007fff2c00af7d $s7SwiftUI11DisplayLinkC07displayD5Timer33_D912470A6161D66810B373079EE9F26ALLyySo09CADisplayD0CF + 77
    30  SwiftUI                             0x00007fff2c00afd6 $s7SwiftUI11DisplayLinkC07displayD5Timer33_D912470A6161D66810B373079EE9F26ALLyySo09CADisplayD0CFTo + 38
    31  QuartzCore                          0x00007fff2af27b66 _ZN2CA7Display11DisplayLink14dispatch_itemsEyyy + 640
    32  QuartzCore                          0x00007fff2b000ac3 _ZL22display_timer_callbackP12__CFMachPortPvlS1_ + 299
    33  CoreFoundation                      0x00007fff23acde8d __CFMachPortPerform + 157
    34  CoreFoundation                      0x00007fff23b0d9c9 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
    35  CoreFoundation                      0x00007fff23b0d028 __CFRunLoopDoSource1 + 472
    36  CoreFoundation                      0x00007fff23b07b64 __CFRunLoopRun + 2516
    37  CoreFoundation                      0x00007fff23b06e66 CFRunLoopRunSpecific + 438
    38  GraphicsServices                    0x00007fff38346bb0 GSEventRunModal + 65
    39  UIKitCore                           0x00007fff47578dd0 UIApplicationMain + 1621
    40  tut1                                0x000000010c36cc3b main + 75
    41  libdyld.dylib                       0x00007fff516ecd29 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

Upvotes: 2

Views: 3872

Answers (1)

Jamie Birch
Jamie Birch

Reputation: 6102

I’ve not used SwiftUI before, but I’m guessing that the actions that you’re doing in updateUI, that should happen only once, instead need to be done during makeUIView:

import SwiftUI
import WebKit

struct WebViewController: UIViewRepresentable {

    let filePath: String

    func makeUIView(context: Context) -> WKWebView  {
        let uiView = WKWebView()
        uiView.configuration.userContentController.add(ContentController(), name: "jsHandler")

        let bundleURL = Bundle.main.resourceURL!.absoluteURL
        let html = bundleURL.appendingPathComponent(filePath)
        uiView.loadFileURL(html, allowingReadAccessTo:bundleURL)

        return uiView
    }

    class ContentController: NSObject, WKScriptMessageHandler {
        func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
            if message.name == "jsHandler"{
                print(message.body)
            }
        }
    }
}

Upvotes: 2

Related Questions