Maxim Rubchinsky
Maxim Rubchinsky

Reputation: 125

Converting Xamarin iOS to Xamarin macOS

I'm using the following class for authentication in Xamarin iOS, but I'm unable to use it Xamarin macOS because SFSafariViewController, SFSafariViewControllerDelegate, and UIViewController cannot be resolved.

Can anyone help me with what I should use to replace those classes in order to use this in a Xamarin macOS application?

public class PlatformWebView : SFSafariViewControllerDelegate, IBrowser
    {
    private SafariServices.SFSafariViewController m_Safari;
    private readonly UIViewController r_Controller;

    public PlatformWebView(UIViewController i_Controller)
    {
        r_Controller = i_Controller;
    }

    public override void DidFinish(SFSafariViewController i_Controller)
    {
        ActivityMediator.Instance.Send("UserCancel");
    }

    public Task<BrowserResult> InvokeAsync(BrowserOptions i_Options)
    {
        if (string.IsNullOrWhiteSpace(i_Options.StartUrl))
        {
            throw new ArgumentException("Missing StartUrl", nameof(i_Options));
        }

        if (string.IsNullOrWhiteSpace(i_Options.EndUrl))
        {
            throw new ArgumentException("Missing EndUrl", nameof(i_Options));
        }

        // must be able to wait for the intent to be finished to continue
        // with setting the task result
        TaskCompletionSource<BrowserResult> tcs = new TaskCompletionSource<BrowserResult>();

        // create Safari controller
        m_Safari = new SafariServices.SFSafariViewController(new NSUrl(i_Options.StartUrl));
        m_Safari.Delegate = this;

        ActivityMediator.MessageReceivedEventHandler callback = null;
        callback = async (i_Response) =>
        {
            // remove handler
            ActivityMediator.Instance.ActivityMessageReceived -= callback;

            if (i_Response == "UserCancel")
            {
                tcs.SetResult(new BrowserResult
                {
                    ResultType = BrowserResultType.UserCancel
                });
            }
            else
            {
                // Close Safari
                await m_Safari.DismissViewControllerAsync(true);

                // set result
                tcs.SetResult(new BrowserResult
                {
                    Response = i_Response,
                    ResultType = BrowserResultType.Success
                });
            }
        };

        // attach handler
        ActivityMediator.Instance.ActivityMessageReceived += callback;

        // launch Safari
        r_Controller.PresentViewController(m_Safari, true, null);

        // need an intent to be triggered when browsing to the "io.identitymodel.native://callback"
        // scheme/URI => CallbackInterceptorActivity
        return tcs.Task;
    }
}

public class ActivityMediator
    {
    public delegate void MessageReceivedEventHandler(string i_Message);

    private static ActivityMediator s_Instance;

    public static ActivityMediator Instance
    {
        get
        {
            if (s_Instance == null)
            {
                s_Instance = new ActivityMediator();
            }

            return s_Instance;
        }
    }

    private ActivityMediator()
    {
    }

    public event MessageReceivedEventHandler ActivityMessageReceived;

    public void Send(string i_Response)
    {
        ActivityMessageReceived?.Invoke(i_Response);
    }
}

Upvotes: 2

Views: 201

Answers (1)

SushiHangover
SushiHangover

Reputation: 74144

"SafariServices" are not available on macOS.

WebKit's WKWebView and WebView are, if you are targeting OS X 10.10 and above, Apple recommends using WKWebView.

re: https://developer.apple.com/documentation/webkit/wkwebview?language=objc

Upvotes: 1

Related Questions