9 Replies
      Latest reply on Oct 9, 2017 7:58 AM by mattn
      AmazingAl Level 1 Level 1 (0 points)

             Hi, thank you for reading the following questions:


             UIWebView can intercept network requests by registering NSURLProtocol sub-type like NSURLProtocol registerClass:[RNCachingURLProtocol class]].  Therefore, local resource files (such as: js,css,png) can be modified or uploaded.

            However, NSURLProtocol is not supported by WKWebView by default. If registered with a private API, WKWebView can intercept local resources in the way UIWebView does. The codes are as follows:


        Class cls = NSClassFromString(@"WKBrowsingContextController");
        SEL sel = NSSelectorFromString(@"registerSchemeForCustomProtocol:");
        if ([cls respondsToSelector:sel]) {  
            [cls performSelector:sel withObject:@"http"];
            [cls performSelector:sel withObject:@"https"];
        }

         

            Regard to this, I’d like to know:

                1.Will there be any risk if I use the above API in WKWebView? Is there any chance that my App would be rejected by App Review?
                2. If the above private API is risky, is there any better solutions for this problem?

        Thanks again!

        • Re: Question on using private API in WKWebView
          iTen Level 2 Level 2 (80 points)

          If it is Apple private, you will be caught during app review and submission.

          • Re: Question on using private API in WKWebView
            eskimo Apple Staff Apple Staff (12,475 points)

            1. Will there be any risk if I use the above API in WKWebView?

            What iTen said but also…

            This is not just about App Review; there’s also a significant binary compatibility risk associated with using private APIs.  You don’t want to build a core part of your app’s functionality on an unstable foundation.  If something changes in the OS and that foundation goes away, your app collapses and there’s no way to rebuild it.

            2. If the above private API is risky, is there any better solutions for this problem?

            iOS 11 has a new mechanism for implementing custom resource loading, namely WKURLSchemeHandler.  You can learn more about this in WWDC 2017 Session 220 Customized Loading in WKWebView.

            Whether this meets your needs depends on your specific requirements.  Notably, WKURLSchemeHandler only lets you implement custom URL schemes, it does not let you override the built-in handling of the http and https scheme.  But perhaps you can change the scheme, either on your origin server or via a user script.

            Share and Enjoy

            Quinn “The Eskimo!”
            Apple Developer Relations, Developer Technical Support, Core OS/Hardware
            let myEmail = "eskimo" + "1" + "@apple.com"

              • Re: Question on using private API in WKWebView
                AmazingAl Level 1 Level 1 (0 points)

                Thanks, Quinn. You said that I can refer to the new iOS 11 mechanism. However, I didn't find any detailed description on WKURLSchemeHandler either in Apple Forum or iOS 11 SDK. Is there any way that I can see the demo code or demo program of WKURLSchemeHandler?

                Thanks for reading.

                  • Re: Question on using private API in WKWebView
                    eskimo Apple Staff Apple Staff (12,475 points)

                    I’m not aware of any official sample code for this.  However, the API is pretty straightforward and has good doc comments.  That, combined with the overview from the WWDC session, should allow you to get started.

                    Give it a while and see what you get.

                    Share and Enjoy

                    Quinn “The Eskimo!”
                    Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                    let myEmail = "eskimo" + "1" + "@apple.com"

                      • Re: Question on using private API in WKWebView
                        mattn Level 1 Level 1 (10 points)

                        Has anyone actually gotten a WKURLSchemeHandler to work? I'm calling

                         

                                self.wv.configuration.setURLSchemeHandler(MySchemeHandler(),
                                                                          forURLScheme: "test")
                        

                         

                        But although my HTML tries to fetch data from a `test:1` URL, no code in MySchemeHandler is ever called, and in fact there is no evidence that the code worked at all: `self.wv.configuration.urlSchemeHandler(forURLScheme: "test")` is nil.

                         

                        It seems like this feature, though much discussed in the video, might be largely aspirational.

                          • Re: Question on using private API in WKWebView
                            eskimo Apple Staff Apple Staff (12,475 points)

                            But although my HTML tries to fetch data from a test:1 URL, no code in MySchemeHandler is ever called …

                            I don’t have time to do an end-to-end test of this right now but but I definitely got further than you (-:  Here’s what I did different:

                            • I used x-qqqtest rather than test, just in case there’s some sort of built-in test scheme.

                            • I used x-qqqtest://some/random/path as the URL to make it look more ‘real’.

                            • I used self as my scheme handler, like so:

                              override func loadView() {
                                  let config = WKWebViewConfiguration()
                                  config.setURLSchemeHandler(self, forURLScheme: "x-qqqtest")
                                  let webView = WKWebView(frame: CGRect.zero, configuration: config)
                                  webView.navigationDelegate = self
                                  self.view = webView
                              }
                              
                              
                              func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
                                  NSLog("start called")
                              }
                              
                              
                              func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
                                  NSLog("stop called")
                              }

                              -

                            I suspect that the last point is key.  It wouldn’t surprise me if you’re having problems because the web view configuration holds a weak reference to the scheme handler and you’re not holding it in memory yourself.

                            Share and Enjoy

                            Quinn “The Eskimo!”
                            Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                            let myEmail = "eskimo" + "1" + "@apple.com"

                              • Re: Question on using private API in WKWebView
                                mattn Level 1 Level 1 (10 points)

                                No, the reference is a strong reference. (Indeed, it can easily cause a memory leak of your whole darned view controller if you are not careful.) The problem turns out to be that the start of the code has to be exactly what you did. But you'll notice that that is not what I did. You cannot say what I said:

                                 

                                self.wv.configuration.setURLSchemeHandler(MySchemeHandler(),  forURLScheme: "test")
                                

                                 

                                Once the configuration has been assigned to (or born with) the web view, setURLSchemeHandler always fails. I regard that as a bug and have reported it. Now that WKWebView is an object in the Interface Builder Object library, it is wrong to expect that I will always be making the web view by hand.