2

In iOS 13, UIScene is used. Codes in AppDelegate.cs must be moved into SceneDelegate.cs to support multiple windows of the same app in Split View.

For Xamarin.Forms, AppDelegate.cs uses LoadApplication (new App()) to launch an instance of App.cs in the Xamarin.Forms. LoadApplication is found in Xamarin.Forms.Platform.iOS.FormsApplicationDelegate.

What is the equivalent in SceneDelegate.cs to launch an instance of App.cs in the Xamarin.Forms?

Tek Mun
  • 97
  • 9
  • Hi , there is a `Main.cs` in Xamarin.iOS , that's the enter of App . And in `SceneDelegate.cs` , you can specify root controller to lauch or other scences to use . You can detail the scene you want to achieve , then I will check that . – Junior Jiang May 01 '20 at 09:19
  • Main.cs launches AppDelegate. In the AppDelegate.cs, the function FinishedLaunching will return true if iOS >= 13. Then, it will call WillConnect function in SceneDelegate.cs. Inside this function, I need to initialize an instance of App class in App.xaml.cs in the Xamarin.Forms common code. – Tek Mun May 01 '20 at 10:36

2 Answers2

2

From the app lifecycle of xamrin forms :

  • iOSMain method > AppDelegate > App > ContentPage .
  • AndroidMainActivity > App > ContentPage

We will see that Main method invoke App class before , if need a instance of App from iOS , generally will try as follow :

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.Init();
    LoadApplication(new App(app)); // pass app to Forms 

    return base.FinishedLaunching(app, options);
}

However ,Forms can not using UIKit (error screenshot).

enter image description here

In xamarin forms , there is DependencyService to load navtive method . Therefore, suggest that using DependecyService to call app from iOS native AppDelegate.cs .

About using SceneDelegate.cs in Xamarin Forms , there is no SceneDelegate.cs file in iOS solution now . I will check that whether be possible in Xamarin Forms .

==================================Update==============================

If want to deal with a universal link in AppDelegate.cs , you need to do something in continueUserActivity method as follow :

public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
   //return base.ContinueUserActivity(application, userActivity, completionHandler);
    if(userActivity.ActivityType == NSUserActivityType.BrowsingWeb)
    {
        NSUrl url = userActivity.WebPageUrl;
        // other code
    }
    return true;
}

==================================Update===============================

Finally , found that it is possible to add SceneDelegate to a Xamarin Forms project. A new Xamarin Forms project does not come with the necessary SceneDelegate.cs or .storyboard files, so these need to be added. After adding these files, the info.plist needs to be updated with the UIApplicationSceneManifest key, which will contain more needed keys.

The additions to info.plist are shown here: https://learn.microsoft.com/en-us/xamarin/ios/platform/ios13/multi-window-ipad#project-configuration (just UIApplicationSceneManifest and everything under)

The two things to note are that:

    1. The sample has issues with navigation working properly when having multiple windows of the app running.
    1. This is not an official sample, as Xamarin.Forms does not currently offer official support for using mutiple Scenes with an iOS application.

The unofficial Xamarin.Forms sample is here:https://www.dropbox.com/s/sdxq5me7vcdmuf9/XamFormsiOSMultiWindow.rar?dl=0

Junior Jiang
  • 12,430
  • 1
  • 10
  • 30
  • In iOS 13, SceneDelegate.cs is used to support multiple windows of the same app in Split View. (http://www.iphonehacks.com/2019/08/how-open-multiple-windows-same-apps-ipad.html). OneDrive app on iPadOS13 is an example. (https://www.onmsft.com/news/microsofts-onedrive-app-ios13-multiple-windows-apple-ipad) In iPadOS13, the path is Main method > AppDelegate > SceneDelegate > App > ContentPage – Tek Mun May 05 '20 at 02:53
  • @TekMun Hi ,I know `SceneDelegate.cs` exists from iOS 13 ,and it exists in Xamarin.iOS project . My answer is about Xamarin.Forms project . Are you in a Forms project ? – Junior Jiang May 05 '20 at 03:01
  • I am in the Forms project and I would like to use SceneDelegate.cs in my Forms project. – Tek Mun May 05 '20 at 05:56
  • @TekMun I will check that how to use `SceneDelegate.cs` in Forms , if solution will share here . – Junior Jiang May 05 '20 at 07:48
  • Ability to support all new iOS features in Xamarin.Forms is useful. – Tek Mun May 06 '20 at 07:23
  • @JuniorJiang-MSFT Any news on how to use SceneDelegate.cs in Forms? I need to use its OpenUrl method to support app links. – Rye bread May 18 '20 at 11:07
  • @Rugbrød Sorry for no good news by using `SceneDelegate.cs` in Forms .However , if want to use `OpenUrl` method , you also can use that method in `AppDelegate.cs` in Forms . – Junior Jiang May 19 '20 at 02:07
  • AppDelegate.OpenUrl seems to no longer work in iOS 13 – Rye bread May 19 '20 at 07:14
  • @Rugbrød I have tested that and it works in iOS 13 . How do you call this method from another application ? – Junior Jiang May 19 '20 at 07:32
  • I click on a universal link, the app opens but it does not seem to invoke OpenUrl. – Rye bread May 19 '20 at 07:34
  • @Rugbrød Hi , a universal link can not call `OpenUrl` method , you should deal with that in `continueUserActivity` method . – Junior Jiang May 19 '20 at 07:40
  • @Rugbrød I have updated answer , you can have a look at that when you have time :-) – Junior Jiang May 19 '20 at 07:56
  • @Rugbrød Hi , good news ! I have found an unofficail xamarin forms sample for ios can support `SceneDelegate` .I will update that in answer . – Junior Jiang May 21 '20 at 02:21
0

It seems this issue has been resolved in MAUI. Just inherit from MauiUISceneDelegate for your SceneDelegate class and the framework will take car of the rest:

[Register("SceneDelegate")]
public class SceneDelegate : MauiUISceneDelegate
{
}

And then in your info.plist file:

<key>UIApplicationSceneManifest</key>
<dict>
    <key>UIApplicationSupportsMultipleScenes</key>
    <true/>
    <key>UISceneConfigurations</key>
    <dict>
        <key>UIWindowSceneSessionRoleApplication</key>
        <array>
            <dict>
                <key>UISceneConfigurationName</key>
                <string>__MAUI_DEFAULT_SCENE_CONFIGURATION__</string>
                <key>UISceneDelegateClassName</key>
                <string>SceneDelegate</string>
            </dict>
        </array>
    </dict>
</dict>

I wish there was an equally clean solution for Xamarin.Forms as we have not migrated our app to MAUI yet.

Hope this helps!

*Update:

Junior Jiang's solution did work for me, but I had to make a few changes to get it to work:

  1. Uncomment the following lines in SceneDelegate.cs:

    //var ad = new AppDelegate();

    //ad.GetUI();

    ...

    //Window.RootViewController = ad.Window.RootViewController;

  2. Then add the following line after the uncommented code in SceneDelegate.cs

    Window.MakeKeyAndVisible();

I made a few additional changes that are not specifically required, but probably a bit better in terms of resource usage, such as rather resolving appDeleggate as follows:

var appDelegate = (AppDelegate)UIApplication.SharedApplication.Delegate;

And instead returning the created Xamarin.Forms app in GetUI method (in AppDelegate) to be used in SceneDelegate, instead of creating another one in SceneDelegate.

One limitation that I did notice is that I could no longer see iOS alert messages, so I used a custom syncfusion popup instead.

CVStrydom
  • 11
  • 5