UIWebView Deprecation and Xamarin.Forms

Gerald Versluis

Gerald

A little while ago, Apple started sending out warning messages about the UIWebView deprecation. This has not gone unnoticed by our Xamarin.Forms users, who directly created an issue for it. Today we have some great news to share: we have a solution for you! This post will give you a bit of background about our considerations and of course, how to avoid rejection to the Apple App Store. 

The History of UIWebView 

UIWebView has already been around since iOS 2.0 but has been deprecated since iOS 8.0. Its successor, WKWebViewof course, does the same thing functionally but has some advantages over the old UIWebView. 

As soon as the UIWebView deprecation became known, the Xamarin.Forms team worked to make a replacement WKWebViewRenderer. While it has been available in Forms for a long time now, the default was still the UIWebViewRenderer. 

Shortly after the introduction of iOS 13, Apple decided to send out warning messages about the UIWebView deprecation. The warning would read:  

ITMS-90809: Deprecated API Usage – Apple will stop accepting submissions of apps that use UIWebView APIs. See https://developer.apple.com/documentation/uikit/uiwebview for more information.

After you’ve corrected the issues, you can use Xcode or Application Loader to upload a new binary to App Store Connect.

This warning was still a warning and would not prevent you from publishing your app at the time. A few months after this, Apple announced that as of April 2020 they reject new apps still referencing UIWebView. For updates to apps the deadline is December 2020. Of course, we want to be ready well before then, and we are.  

Maintain Backwards Compatibility for Xamarin.Forms 

With Xamarin.Forms we strive to maintain backwards compatible the best we can. This issue challenged that quite a bit. As you might know, or maybe have experienced, the linker for the iOS platform can be pretty aggressive. What it does is strip out any APIs that are not referenced from your code in order to make the resulting binary of your app smaller. 

Because of this, we thought the solution would be to simply switch the default renderer to the WKWebViewRenderer. By doing that, there would be no reference to the UIWebView anymore and it would be taken out by the linker. 

While working on this, we discovered that the linker does a fantastic job, but the Xamarin.Forms binary was excluded from linking by default. That would mean as long as the UIWebViewRenderer file would exist in our codebase, ultimately apps would be rejected. 

This was a problem, because if we want to keep up our backwards compatibility game, we couldn’t just delete the UIWebViewRenderer. This would potentially break custom renderers or other code that referenced this class implemented by Xamarin.Forms users. Therefore, we went looking for another solution. 

Xamarin.iOS Team to the Rescue 

During our quest for a solution we had multiple options. For example: making stubs or rewriting the UIWebViewRenderer to use WKWebView underneath. The most obvious option, however, would be to find out if we could make the linker work for Xamarin.Forms as well. 

We have worked closely with the Xamarin.iOS team to make that happen. On top of that, we are proud to say that we have a solution that does exactly that. 

Because Xamarin.Forms has been excluded from the linker since forever, we first want to make sure that everything continues to work as expected. Because of that, this new linker behavior is behind a feature flag for now. 

Prevent App Store Rejection, Today! 

The solution only involves three steps: 

  • Use the right versions of Xamarin.Forms and Xamarin.iOS. 
  • Add a flag to the build configuration. 
  • Build and submit your app to the App Store and celebrate! 

On the Xamarin.Forms side we also had to make some changes to make all this work correctly. These new changes are part of Xamarin.Forms 4.5, including the pre-releases. Make sure that you are using the Forms 4.5 or newer NuGet package in your projects. 

You also need to make sure that you are using Xamarin.iOS 13.10.0.17. You can check this from Visual Studio. This version of Xamarin.iOS is included with Visual Studio for Mac 8.4.1 and Visual Studio 16.4.3 and up. 

With that in place, you can simply go to your iOS project, open the project properties and add this flag in the additional mtouch arguments field: --optimize=experimental-xforms-product-type this flag works together with the Linker Behavior set to SDK Only or All. If for any reason you see errors when setting the Linker Behavior to All, this is most likely a problem within the app code or a 3rd party library that is not linker safe. For more information on the linker, please refer to the docs.

In the screenshot below you can see the end result in Visual Studio for Mac.

Filling the additional mtouch arguments field in your iOS project in Visual Studio for Mac screenshot
Filling the additional mtouch arguments field in your iOS project in Visual Studio for Mac screenshot

This setting can be applied per build configuration so make sure that you put it in the right one. That will probably be the iPhone/Release build configuration which is typically used for distribution builds. Also make sure the Linker behavior is set to either SDKs only or Link All.

UIWebView Deprecation Fixed

That’s it! Now create a new build, submit it to the App Store and all is good.

All of this is described with a bit more detail in the documentation.

72 comments

Comments are closed. Login to edit/delete your existing comments

  • Avatar
    Andrew Bailie

    I’ve just tried this on my app and just got a completely black screen after the launch screen.
    If I take out the argument everything works as expected again. Would this be the expected behaviour if one of the included nugets referenced UIWebView directly, or should the linker just include the UIWebView and allow everything to work on?
    I’ve tried this on the simulator and an iPhone.

    Visual Studio Community 2019 for Mac Version 8.4.4 (build 91)
    Xamarin.iOS Version: 13.10.0.17
    Xamarin.Forms Version 4.5.0.282-pre4

    other nugets:

    CarouselView.FormsPlugin Version 5.2.0
    Com.Airbnb.Xamarin.Forms.Lottie Version= 3.0.4Microsoft.AppCenter Version= 2.6.4
    Microsoft.AppCenter.Analytics Version= 2.6.4
    Microsoft.AppCenter.Crashes Version= 2.6.4
    Newtonsoft.Json Version 12.0.3
    Plugin.Fingerprint Version= 2.0.0-alpha.6
    Prism.Plugin.Popups Version 7.2.0.759
    SkiaSharp Version 1.68.2-preview.29
    Xam.Plugin.Connectivity Version 4.0.0.190-beta
    Xam.Plugin.DeviceInfo Version 4.2.0-beta
    Xamarin.FFImageLoading.Svg Version 2.4.11.982
    Xamarin.FFImageLoading.Svg.Forms Version 2.4.11.982
    Xamarin.FFImageLoading.Transformations Version 2.4.11.982
    Prism.Unity.Forms Version 7.2.0.1422
    ZXing.Net.Mobile Version 2.4.1
    ZXing.Net.Mobile.Forms Version 2.4.1
    Xamarin.Essentials Version 1.4.0-pre2

    • Gerald Versluis
      Gerald VersluisMicrosoft employee

      Hey Andrew,

      Sorry about that! I see there is already an issue logged in regard to this here. Would you be able to verify if that is the same issue and add your details there?

      If you believe it’s something different, please open another issue on the repository.

      Thanks!

      • Avatar
        Juan Cadena

        I have a similar problem, using the version 4.5.0.282-pre4 of Xamarin.Forms the message “Default constructor not found for type Xamarin.Forms.Platform.iOS.FrameRenderer” is displayed.

        • Joshua Camaioni
          Joshua Camaioni

          I am having a similar issue as Juan Cadena. This is very frustrating.

          Default constructor not found for type Xamarin.Forms.Platform.iOS.SwitchRenderer

          Please help!! I’ll keep looking for a solutions as well and post back if I find something. Thanks.

        • test 1
          test 1

          Hi Gerald Versluis,
          Note : 1. Linker Behaviour – Link All” – Worked fine with Blank and getting issue with Shell.
          2. Linker Behaviour – Don’t Link” – Getting warning mail from Apple when trying to upload to test flight.
          1. I too have an similar issue, its because of using Xamarin forms(4.5.0.356) with Shell and UIWebView Depreciation solution.
          2. So i tried with an empty shell application and its the
          error :System.MissingMethodException: ‘Default constructor not found for type Xamarin.Forms.Platform.iOS.ShellRenderer’
          3. And also i tried with blank application with UIWebView Depreciation Solution by keeping “Linker Behaviour – Link All” it’s Working fine.

          I think some issue with shell, So please help me out from this, Thanks in advance.

      • Avatar
        Andrew Bailie

        Hi Gerald,

        Sorry for the delay in getting back to you, but I was on vacation for a few weeks.

        I’m not sure if this was the same issue but it’s quite likely. I know that in debug build I just got a black screen and looking at the threads showed pretty much nothing was running, while a release build caused a full out crash.

        I just updated my Xamarin Forms and tried again and now all is good in the world.

        Visual Studio Community 2019 for Mac Version 8.4.7 (build 17)
        Xamarin.iOS Version: 13.10.0.21
        Xamarin.Forms Version 4.5.0.356

        other packages:

        CarouselView.FormsPlugin Version 5.2.0
        Com.Airbnb.iOS.Lottie Version 2.5.10
        Com.Airbnb.Xamarin.Forms.Lottie Version 3.0.4
        Microsoft.AppCenter.Analytics Version 2.6.4
        Microsoft.AppCenter.Crashes Version 2.6.4
        Microsoft.Azure.Mobile.Client Version 4.1.2
        Plugin.Fingerprint Version 1.4.9
        Prism.Plugin.Popups Version 7.2.0.759
        SkiaSharp Version 1.68.2-preview.29
        Xam.Plugin.Connectivity Version 4.0.0.190-beta
        Xam.Plugin.DeviceInfo Version 4.2.0-beta
        Xam.Plugins.Forms.KeyboardOverlap Version 1.0.0.4
        Xamarin.FFImageLoading.Svg Version 2.4.11.982
        Xamarin.FFImageLoading.Svg.Forms Version 2.4.11.982
        Xamarin.FFImageLoading.Transformations Version 2.4.11.982
        Prism.Unity.Forms Version 7.2.0.1422
        ZXing.Net.Mobile Version 2.4.1
        ZXing.Net.Mobile.Forms Version 2.4.1
        Xamarin.Essentials Version 1.5.0

        Thanks,

        Andrew

    • Gerald Versluis
      Gerald VersluisMicrosoft employee

      I’m not sure what you mean by that. If you are referring to the screenshot showing the Debug | iPhone Simulator configuration then you are absolutely right. It doesn’t make sense to configure that there. You should do it in App Store | iPhone or Release | iPhone. Whichever you use to publish to the App Store.

      I will get that fixed.

  • Nimoh
    Nimoh

    Hi Gerald,

    I am hoping you will be able to help me as I am stuck. The apple depreciation warning still persists even after following the above steps. To test if the issue was with my nugets, I create a new blank xamarin forms app and added the below nugets (without referencing them in code) and surprisingly I did not get the warning error. At this stage, I cannot figure out what I am missing. This is my csproj file and list of nugets. Please advise. Thanks

    Csproj file
    ‘$(Configuration)|$(Platform)’ == ‘Release|iPhone’ ”
    DebugType -none – DebugType
    Optimize – true – Optimize
    OutputPath – bin\iPhone\Release – OutputPath
    ErrorReport – prompt – ErrorReport
    WarningLevel – 4 -WarningLevel
    MtouchArch – ARM64 – MtouchArch
    ConsolePause – false – ConsolePause
    CodesignKey – xxx – CodesignKey
    CodesignEntitlements – Entitlements.plist – CodesignEntitlements
    MtouchExtraArgs –optimize=experimental-xforms-product-type MtouchExtraArgs
    MtouchLink – Full – MtouchLink

    Nugets:
    Microsoft.AppCenter.Analytics=3.0.0
    Microsoft.AppCenter.Crashes=3.0.0
    Prism.DryIoc.Forms=7.2.0.1422
    PropertyChanged.Fody=3.2.6
    Xam.Plugins.Settings=3.1.1
    Xamarin.Forms=4.5.0.396
    Xamarin.Essentials=1.5.0
    Xamarin.Forms.Visual.Material=4.6.0.379-pre1
    Xamarin.FFImageLoading.Svg.Forms=2.4.11.982
    Auth0.OidcClient.iOS=3.1.2

    System
    Visual Studio Community 2019 for Mac Version 8.4.8 (build 2)
    Xamarin.iOS Version: 13.10.0.21

  • Avatar
    idchlife idchlife

    Hi! Thank you for the blog post. Unfortunately, this solution does not work for me 🙁

    TLDR: how to remove UIWebView reference WITHOUT using linker at all? It basically killed my app.

    I have already huge app with many non-xamarin libraries (csv reader, json reader, http api libraries, barcode generators etc) and I received email from Apple about my app using UIWebView. From my side I am using WebView control, without any specific UIWebView usage under the hood (in my code).

    I followed your advice and used Link All and mtouch argument.

    In Debug I receive typical here

    `
    System.MissingMethodException has been thrown

    Default constructor not found for type MyApp.Services.PagesService
    `

    while using DependencyService.Get()

    In my Release version in TestFlight I’m getting only app crashes. I don’t know whether it is same error or not.

    I’m ok with not using the Linker, I just wan’t my app to be published and to work, would it be 40mb or 90mb (like now). And right now app can’t be started on devices without hand checking every library and adding “preserve” for every small class in project for linker not to delete.

    How to remove UIWebView reference without using the linker?

    I’m using everything latest preview. VS for Mac, Xamarin.Forms, etc, etc

    • Gerald Versluis
      Gerald VersluisMicrosoft employee

      Thank you for reaching out! I’m sorry it doesn’t work for you out of the box.

      In regard to your `MissingMethodException`, you should be able to fix that by adding this attribute: `[Preserve(Conditional = true)]` to the constructors of your code. As you can see in our code here https://github.com/xamarin/Xamarin.Forms/commit/669ad9687b4f9921a95a0c6eb24f46bed1835b71#diff-01c9db0ba66f8f2ebc6ea9eec3638e96.

      That should preserve the constructors while linking and should fix your issue 🙂

      • Avatar
        idchlife idchlife

        Thanks for quick reply! It did use Preserve for my services which I’m using via DependencyService (default one in Xamarin Forms), but I’m getting now

        System.Reflection.TargetInvocationException

        Exception has been thrown by the target of an invocation.

        System.MissingMethodException Constructor on type ‘MyApp.Services.Api.AutoGeneratedIAuthenticationApi’ not found.

        I’m using Refit for my api, which heavily relies on reflection to generate apis from interfaces.

        I’m afraid the list of errors will go on because I did not hold myself when installing different packages into the application… Maybe there is another way to remove UIWebView reference which will not include linker and bothering you with variety of errors in my app?

        • Gerald Versluis
          Gerald VersluisMicrosoft employee

          I understand! I’m afraid there isn’t really any other way. Unless you are willing to compile a version of the Forms source yourself, which will also make you responsible for doing a complete recompile whenever you want to install an update, so I don’t think that would be a viable option.

          There is some additional guidance from the Xamarin.iOS team, which you can find here; https://docs.microsoft.com/en-us/xamarin/ios/release-notes/13/13.16#applications-cannot-use-the-linker-or-change-its-settings

          Especially the part I linked you to (applications that cannot use the linker) might be of interest for you to try.

          Note, that this will require Xamarin.iOS 13.16 as opposed to 13.10 which I mentioned in the blog.

          • Avatar
            idchlife idchlife

            It seems for now the working option is to set Link only SDK with mtouch arguments. (+ Preserve attribute for my services classes constructors)

            Thanks for the help!

            I hope Xamarin will add new option in nearest version to disable UIWebView without linker because many developers will face the same problems as I had and it’s almost April, which means it won’t be pretty for many teams out there.

  • Avatar
    Ramesh Sringeri

    Thanks for the post. Unfortunately I still get a warning from Apple that I am using deprecated APIs. When I build the IPA I do not have a device connected to the mac but use the “Generic Device” option. The build options dialog box does not have an option for Generic Device. Assuming iPhone would work.

    First attempt resulted in app crashes in simulator. But after cleaning all folders and ensuring everything was updated, app does not crash in Simulator.

    Any ideas?

  • Avatar
    Herb Weiner

    I was hoping to find a complete, working, cross platform (iOS and Android) example that uses a WebView.

    https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/webview?tabs=macos was most recently updated 11/04/2019, and includes a link to Download the Sample. So I was optimistic that I could begin here.

    I updated the NuGet packages, updated the Linker behavior and Additional mtouch arguments, and provisioned it with my Certificate, Devices, and Provisioning Profile. Although the app builds successfully, and can be installed on my iPhone, the app quits immediately after launch.

    Please, Please, Please, provide a working cross platform WebView example. Ideally, include the WebView on a xaml page. Once I have a functional example to work with, it should be much easier to update my own app.

    • Avatar
      Herb Weiner

      Some additional information: When i add: –warn-on-type-ref=UIKit.UIWebView in addition to –optimize=experimental-xforms-product-type to the Additional mtouch arguments, I get the following warning messages.

      /Users/herbw/Desktop/Xamarin_Forms___Working_with_WebView/iOS/MTOUCH: Warning MT1502: One or more reference(s) to type ‘UIKit.UIWebView’ already exists inside ‘Xamarin.Forms.Platform.iOS, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null’ before linking (MT1502) (WorkingWithWebview.iOS)
      /Users/herbw/Desktop/Xamarin_Forms___Working_with_WebView/iOS/MTOUCH: Warning MT1503: One or more reference(s) to type ‘UIKit.UIWebView’ still exists inside ‘Xamarin.Forms.Platform.iOS, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null’ after linking (MT1503) (WorkingWithWebview.iOS)

      These are not really much of a surprise. Really, what is required is a working cross platform WebView example that uses WKWebViewRenderer for iOS.

      • Gerald Versluis
        Gerald VersluisMicrosoft employee

        Hi Herb,

        I’m sorry you’re having trouble with this. Please find my testing project here: https://github.com/jfversluis/WebViewTest
        Throughout time I have been testing with this very simple project that shows you all the ingredients you need. Just to verify, just before putting this up I have created a build with this exact solution and it uploads without warnings.

        If you are using Forms 4.5 and up, you should not be worried about the WKWebViewRenderer. This is the default renderer now.

        Important is:
        1. Use the right versions of Forms (4.5) and Xamarin.iOS (13.10) or higher
        2. use the -–optimize=experimental-xforms-product-type flag for the right configuration
        3. Have your linker set to all/full or SDK only

        From there; make sure you don’t have a reference to UIWebView or WebViewRenderer in your own code or have any plugins installed that reference one of the before named classes. One notable one is also in my sample project; Xamarin.Forms.Visual.Material. For the time being make sure that you manually install Xamarin.iOS.MaterialComponents version 92 and up.

        If you do all that, things should be fine. If you still have issues, please feel free to reach out directly to gerald.versluis emailsign microsoft.com and we will figure this out 🙂

  • Panneer Selvam
    Panneer Selvam

    Hi , I’m very new to Xamarin forms and facing the same issue, can someone please help

    Nuget packages:

    VIsual studio: – 7.7.4 (mac)
    Mono version – 5.18

    And I changed all webview renderers to “WkWebViewRenderer”

  • Avatar
    Tony Pitman

    I followed this and when I run my app it crashes. So I made the same changes to the Debug build and debug it. It gives an exception on this line:

            public TouchEffect() : base("XamarinDocs.TouchEffect")

    This is in a class that I found some code to do platform specific touch handling. I have a similar named class in my .iOS project. It looks like this:

    using System;
    using System.Linq;
    
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.iOS;
    
    using UIKit;
    
    [assembly: ResolutionGroupName("XamarinDocs")]
    [assembly: ExportEffect(typeof(TouchTracking.iOS.TouchEffect), "TouchEffect")]
    
    namespace TouchTracking.iOS
    {
        public class TouchEffect : PlatformEffect
        {
            UIView view;
            TouchRecognizer touchRecognizer;
    
            protected override void OnAttached()
            {
                // Get the iOS UIView corresponding to the Element that the effect is attached to
                view = Control == null ? Container : Control;
    
                // Get access to the TouchEffect class in the .NET Standard library
                TouchTracking.TouchEffect effect = (TouchTracking.TouchEffect)Element.Effects.FirstOrDefault(e => e is TouchTracking.TouchEffect);
    
                if (effect != null && view != null)
                {
                    // Create a TouchRecognizer for this UIView
                    touchRecognizer = new TouchRecognizer(Element, view, effect); 
                    view.AddGestureRecognizer(touchRecognizer);
                }
            }
    
            protected override void OnDetached()
            {
                if (touchRecognizer != null)
                {
                    // Clean up the TouchRecognizer object
                    touchRecognizer.Detach();
    
                    // Remove the TouchRecognizer from the UIView
                    view.RemoveGestureRecognizer(touchRecognizer);
                }
            }
        }
    }

    The exception says it can’t find the constructor. If I remove the extra linker option that does NOT solve it. I have to change the linker option from Link All back to Link Framework SDKs Only. Then it works fine in Debug or Release.