A better way to present a SFSafariViewController in SwiftUI

A better way to present a SFSafariViewController in SwiftUI

A new system bug was introduced on iOS 14 beta 6, where the interactive pop gesture of SFSafariViewController is not working. Before the new beta is released, the gesture of BetterSafariView also may not work as expected on iOS 14.

A new system bug was introduced on iOS 14 beta 6, where the interactive pop gesture of SFSafariViewController is not working. Before the new beta is released, the gesture of BetterSafariView also may not work as expected on iOS 14.

BetterSafariView

A better way to present a SFSafariViewController or start a ASWebAuthenticationSession in SwiftUI.

Motivation

SwiftUI is a strong, intuitive way to build user interfaces, but was released with some part of existing elements missing. One example of those missing elements is the SFSafariViewController.

Fortunately, Apple provides a way to wrap UIKit elements into SwiftUI views. A common approach to place the SFSafariViewController inside SwiftUI is to create a simple view representing a SFSafariViewController, then present it with a sheet(isPresented:onDismiss:content:) modifier or a NavigationLink button (See RootView.swift in the demo project).

However, there’s a problem in this approach: it can’t present the SFSafariViewController with its default presentation style — a push transition covers full screen. A sheet modifier can present the view only in a modal sheet, and a navigation link shows the two navigation bars at the top so we have to deal with them. This comes down to the conclusion that there’s no option to present it the right way except for using present(_:animated:completion:) method of a UIViewController instance, but it is prohibited and not a good design to access the UIHostingController directly from the SwiftUI view.

BetterSafariView clearly achieves this goal by hosting a simple UIViewController to present a SFSafariViewController as a view’s background. In this way, a ASWebAuthenticationSession is also able to be started without any issue in SwiftUI.

Usage

With the following modifiers, you can use it in a similar way to present a sheet.

SafariView

Modifiers
.safariView(isPresented:onDismiss:content)
.safariView(item:onDismiss:content)
Example
import SwiftUI
import BetterSafariView

struct ContentView: View {

    @State private var presentingSafariView = false

    var body: some View {
        Button(action: {
            self.presentingSafariView = true
        }) {
            Text("Present SafariView")
        }
        .safariView(isPresented: $presentingSafariView) {
            SafariView(
                url: URL(string: "https://github.com/")!,
                configuration: SafariView.Configuration(
                    entersReaderIfAvailable: false,
                    barCollapsingEnabled: true
                )
            )
            .preferredControlTintColor(.systemBlue)
            .dismissButtonStyle(.done)
        }
    }
}

WebAuthenticationSession

Modifiers
.webAuthenticationSession(isPresented:content)
.webAuthenticationSession(item:content)
Example
import SwiftUI
import BetterSafariView

struct ContentView: View {

    @State private var startingWebAuthenticationSession = false

    var body: some View {
        Button(action: {
            self.startingWebAuthenticationSession = true
        }) {
            Text("Start WebAuthenticationSession")
        }
        .webAuthenticationSession(isPresented: $startingWebAuthenticationSession) {
            WebAuthenticationSession(
                url: URL(string: "https://github.com/login/oauth/authorize")!,
                callbackURLScheme: "github"
            ) { callbackURL, error in
                print(callbackURL, error)
            }
            .prefersEphemeralWebBrowserSession(false)
        }
    }
}

Known Issues

  • In .webAuthenticationSession(item:content:) modifier, the functionality that replaces a session on the item's identity change is not implemented, as there is no non-hacky way to be notified when the session's dismissal animation is completed.

Requirements

  • Swift 5.1+
  • iOS 13.0+

Installation

Swift Package Manager

Add the following line to the dependencies in your Package.swift file:

.package(url: "https://github.com/stleamist/BetterSafariView.git", .upToNextMajor(from: "2.2.2"))

Next, add BetterSafariView as a dependency for your targets:

.target(name: "MyTarget", dependencies: ["BetterSafariView"])

Your completed description may look like this:

// swift-tools-version:5.1

import PackageDescription

let package = Package(
    name: "MyPackage",
    dependencies: [
        .package(url: "https://github.com/stleamist/BetterSafariView.git", .upToNextMajor(from: "2.2.2"))
    ],
    targets: [
        .target(name: "MyTarget", dependencies: ["BetterSafariView"])
    ]
)

Xcode

Select File > Swift Packages > Add Package Dependency, then enter the following URL:

https://github.com/stleamist/BetterSafariView.git

For more details, see Adding Package Dependencies to Your App.

Demo

You can compare the behavior of BetterSafariView with the other ways above in the demo project. Check out the demo app by opening BetterSafariView.xcworkspace.

NOTE: This demo project is designed for iOS 14.0+, though the package is compatible with iOS 13.0+.

Download Details:

Author: stleamist

Source Code: https://github.com/stleamist/BetterSafariView

swiftui ios swift mobile-apps

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Top Swift iOS App Development Company in USA

AppClues Infotech is a top Mobile App Development Company in USA building high-quality Android, iOS, and Native apps for Startups, SMBs, & Enterprises. Contact us now!

How To Succeed In Mobile App Wireframe Design?

This article covers everything about mobile app wireframe design: what to do and what not, tools used in designing a mobile or web app wireframe, and more.

How long does it take to develop/build an app?

This article covers A-Z about the mobile and web app development process and answers your question on how long does it take to develop/build an app.

Best Mobile App Development Company | Android and iOS Apps

iPrism Tech is a one of the best and offshore mobile app development company in India, Saudi Arabia and USA. We are a major providers of android, iphone and ipad mobile app development services at economical prices.

Best Swift App Development Company

Apple Swift App Development India: Mobile App Development India is an expert iOS Swift App Development company in India. We develop secure and robust mobile app solutions based on new Apple Swift language.