Integrar con Swift
Safari View Controller integra todo Safari dentro de su aplicaciĆ³n usando un controlador de vista opaco. Es decir, no puede diseƱarlo, no puede interactuar con Ć©l y no puede extraer ningĆŗn dato privado de Ć©l. Como resultado, SFSafariViewController puede aprovechar los datos web seguros del usuario.
En este paso vamos a instalar y configurar las dependencias necesarias para implementar SFSafariViewController en tu proyecto desarrollado en Swift.
InstalaciĆ³n de SFSafariViewController
Client-Side
SFSafariViewController no forma parte del UIKit por lo que, para usarlo, deberĆ”s importar Safari Services Framework que contiene los servicios necesarios para integrar comportamientos de Safari en tu aplicaciĆ³n iOS.
Para instalarlo, ve al archivo en donde desees utilizar Safari View Controller e importa la biblioteca SafariServices.
Main.swift
import SafariServices
Al trabajar con SFSafariViewController, puedes abrir la URL de preferencia con sĆ³lo enviar la URL o agregando algunos ajustes de configuraciĆ³n. A continuaciĆ³n, te mostramos algunos ejemplos de referencia para la implementaciĆ³n de SFSafariViewController.
import SwiftUI
import SafariServices
struct ContentView: View {
var body: some View {
VStack {
Button("Open Preference" ) {
if let url = URL(string:"YOUR-URL-PREFERENCE")
{
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
if let rootViewController = windowScene.windows.first?.rootViewController {
let safariVC = SFSafariViewController(url: url)
rootViewController.present(safariVC, animated: true, completion: nil)
}
}
}
}
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
import SafariServices
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton()
button.setTitle("Open Preference", for: .normal)
button.backgroundColor = .systemBlue
view.addSubview(button)
button.frame = CGRect(x: 100, y: 100, width: 200, height: 50)
button.layer.cornerRadius = 25
button.addTarget(self, action: #selector(openSafariViewController) , for: .touchDown)
}
@objc func openSafariViewController(_ sender: Any) {
if let url = URL(string: "YOUR-URL-PREFERENCE") {
let safariViewController = SFSafariViewController(url: url)
present(safariViewController, animated: true, completion: nil)
}
}
}
CĆ³mo volver a tu App
Client-Side
Los Deep Links, tambiĆ©n conocidos como enlaces profundos, son una forma poderosa de permitir la navegaciĆ³n directa a pantallas o secciones especĆficas de una aplicaciĆ³n mĆ³vil.
Crear un Deep Link
Desde nuestro checkout es posible configurar Deep Links para volver a tu aplicaciĆ³n, ya sea haciendo click en un link de āVolverā, o de forma automĆ”tica al terminar todo un flujo de pago exitoso, para luego ser redirigido a tu App.
Para esto, debemos agregar en la creaciĆ³n de la preferencia de pago las propiedades back_urls
y auto_return
, segĆŗn corresponda.
Para conocer mĆ”s, puedes acceder a la documentaciĆ³n de URLs de retorno.
ConfiguraciĆ³n de la aplicaciĆ³n para la gestiĆ³n del Deep Link
Client-Side
Para configurar un Deep Link nativo en iOS, dirĆgete al archivo <appname>/Info.plist
y agrega el cĆ³digo que se muestra a continuaciĆ³n segĆŗn sea tu caso.
El siguiente ejemplo aplica para un deep link de la forma iosapp://:
plain
<dict>
ā¦
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>your_identifier_here</string>
<key>CFBundleURLSchemes</key>
<array>
<string>iosapp</string>
</array>
</dict>
</array>
ā¦
</dict>
El valor CFBundleURLName
corresponde al identificador de la aplicaciĆ³n (Identifier) y CFBundleURLSchemes
al scheme utilizado en el Deep Link.
Configurar el Deep Link desde Xcode
TambiĆ©n puedes configurar el Deep Link desde Xcode. Para esto, ubĆcate en la informaciĆ³n de tu proyecto y agrega una nueva URL Type
.
Luego, ingresa el identifier
de tu aplicaciĆ³n y la URL Schemes
del Deep Link.
Esto generarĆ” automĆ”ticamente el mismo cĆ³digo que se indicĆ³ anteriormente en el archivo <appname>/Info.plist
.
RecepciĆ³n y gestiĆ³n del Deep Link
Client-Side
En iOS, cuando un deep link intenta redirigir al usuario a la aplicaciĆ³n desde una Safari View Controller es necesario configurar un manejador de este evento para cerrarla y cargar la vista o escena que corresponda.
struct ContentView: View {
@State private var showSuccessView = false
var body: some View {
VStack {
Text("SwiftUI")
.font(.system(size: 36, design: .rounded).weight(.bold)).foregroundColor(.black).padding(.bottom, 8)
Text("POC")
.font(.system(size: 24, design: .rounded)).foregroundColor(.gray).padding(.bottom)
Button("Abrir Safari") {
if let url = URL(string: "YOUR-URL-PREFERENCE") {
UIApplication.shared.windows.first?.rootViewController?.present(UIHostingController(rootView: SafariView(url: url)), animated: true, completion: nil)
}
}.padding(.bottom)
Button("Abrir Congrat") {
showSuccessView = true
}
}
.sheet(isPresented: $showSuccessView) {
SuccessView(isPresented: $showSuccessView)
}
// AquĆ la recepciĆ³n deep link
.onOpenURL { url in
if let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
components.scheme == "iosapp",
components.host == "congrat",
components.path.contains("success") {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
if let presenting = UIApplication.shared.windows.first?.rootViewController?.presentedViewController {
presenting.dismiss(animated: true, completion: nil)
showSuccessView = true
}
}
}
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Desde el AppDelegate.swift o SceneDelegate.swift segĆŗn sea tu caso, recibirĆ”s un Deep Link de la forma iosapp://congrat/success. Luego debĆ©ras cerrar Safari View Controller para cargar una vista llamada SuccessViewController.
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
if let urlContext = URLContexts.first {
let url = urlContext.url
if let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
components.scheme == "iosapp",
components.host == "congrat",
components.path.contains("success") {
if let rootViewController = window?.rootViewController {
let successViewController = SuccessViewController {
rootViewController.dismiss(animated: true, completion: nil)
}
if let presentingViewController = rootViewController.presentedViewController {
presentingViewController.dismiss(animated: true) {
rootViewController.present(successViewController, animated: true, completion: nil)
}
} else {
rootViewController.present(successViewController, animated: true, completion: nil)
}
}
}
}
}
}
Desde el ContentView de la aplicaciĆ³n recibirĆ”s un Deep Link de la forma iosapp://congrat/success y, luego de un intervalo de tiempo, deberĆ”s cerrar Safari View Controller para cargar una vista llamada SuccessView.