May 22nd, 2020

Reuse Xamarin.Forms Pages in an iOS Extension

alexeystrakh
Software Developer Engineer

iOS extensions allow developers to customize existing system behaviors by adding extra functionality to iOS and macOS Extension Points. Such as custom context actions, password autofill, and incoming calls filters. Even actions like notification content modifiers. Xamarin.iOS supports extensions and this awesome guide will walk you through creating an iOS extension using Xamarin tools.

iOS Extensions

Extensions are distributed as part of a Container app and activated from a specific Extension Point in a Host app. The Container app is usually a simple iOS application. It provides a user with information about the Extension. As well as how to activate and how to use it. There are three main approaches to sharing code between an Extension and a Container app:

  1. Common iOS Project

    Put all of the shared code between the Container and the Extension into a shared iOS library. Then, reference the library from both projects. Usually, the shared library contains native UIViewControllers from a Xamarin.iOS library.

  2. File Links

    In some cases, the Container app provides most of the functionality. All while the Extension needs to render a single `UIViewController`. With few files to share, it is common to add a file link to the Extension app. This is done from the file located in the Container app.

  3. Common Xamarin.Forms Project

    When using the Xamarin.Forms framework, app pages already shared with another platform (such as Android), reimplement required pages natively in the Extension project. This is because the iOS Extension works with native UIViewControllers and not Xamarin.Forms pages.

Additional steps are needed to use Xamarin.Forms in the iOS Extension. These steps are explained below.

Xamarin.Forms in an iOS Extension Project

The ability to use Xamarin.Forms in a native project is provided via Native Forms. It allows ContentPage-derived pages to be added directly to native Xamarin.iOS projects. The CreateViewController extension method converts an instance of a Xamarin.Forms page to a native UIViewController. This can then be used or modified as a regular controller. Use the same approach with an iOS Extension as a special kind of a native iOS project.

Important! There are many known limitations for iOS Extensions. Although you can use Xamarin.Forms, do so very carefully. Monitor memory usage and startup time. Otherwise, the Extension could be terminated by iOS without a graceful way to handle it.

How Does it Work

  1. Create an empty Xamarin.Forms project and customize your MainPage.xaml.
  2. Add a new Xamarin.iOS Extension project using one of the available Visual Studio templates.
  3. Add Xamarin.Forms and the shared library references to the Extension project.
  4. Modify an entry point to initialize Xamarin.Forms and create pages.
    • Per iOS requirements, an Extension must define the entry point in Info.plist as NSExtensionMainStoryboard or NSExtensionPrincipalClass.
  5. Once the entry point is activated (in our case the ActionViewController.ViewDidLoad method), create an instance of a Xamarin.Forms page and show it to a user.
  6. Open the entry point and replace the ViewDidLoad method with the following implementation:
public override void ViewDidLoad()
{
    base.ViewDidLoad();

    // Initialize Xamarin.Forms framework
    global::Xamarin.Forms.Forms.Init();
    // Create an instance of XF page with associated View Model
    var xfPage = new MainPage();
    var viewModel = (MainPageViewModel)xfPage.BindingContext;
    viewModel.Message = "Welcome to XF Page created from an iOS Extension";
    // Override the behavior to complete the execution of the Extension when a user press the button
    viewModel.DoCommand = new Command(() => DoneClicked(this));
    // Convert XF page to a native UIViewController which can be consumed by the iOS Extension
    var newController = xfPage.CreateViewController();
    // Make sure the presentation style is set to full screen to avoid rendering the original entry point
    newController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
    // Present new view controller as a regular view controller
    this.PresentModalViewController(newController, false);
}

MainPage

The MainPage is instantiated using a standard constructor. Before you can use it in the Extension, convert it to a native UIViewController. Do this by using the CreateViewController extension method. Build and run the application.

Activation

To activate the Extension, navigate to the Safari browser. Type in any web address, e.g. microsoft.com, press navigate. Then press the Share icon at the bottom of the page to see the available action extensions. From the list of available extensions, select the MyAction Extension. The Extension is activated and the Xamarin.Forms page is displayed to the user. All the bindings and commands work as in the Container app:

Xamarin Forms in an iOS Extension - full demo

Important! For the device build, make sure to use proper build settings and the Release configuration as described here.

Find the sample source code here. As well as a complete walkthrough guide here.

Useful Links

Author

alexeystrakh
Software Developer Engineer

I'm a Software Developer Engineer for Mobile Customer Advisory Team, aka MobCAT, at Microsoft, focused on Xamarin. A .NET developer since 2005, and a mobile app developer since 2011. My goal is to make sure that all the developers have amazing and joyful experiences working with the Microsoft developer tools and the tools are waiting for developers and not vice versa.

1 comment

Discussion is closed. Login to edit/delete existing comments.

  • idchlife idchlife

    Thank you for this wonderful post! Not everyone knows about using XF pages in iOS app extensions.