Когда я могу использовать SFSafariViewController, WKWebView или UIWebView с универсальными ссылками?

В разделе Universal Links Руководство по программированию приложений для iOS, Apple говорит:

Если вы создаете экземпляр SFSafariViewController, WKWebView или UIWebView объект для обработки универсальной ссылки, iOS открывает ваш сайт в Safari вместо открытия вашего приложения. Однако, если пользователь называет универсальный ссылка из встроенного SFSafariViewController, WKWebView или Объект UIWebView, iOS открывает ваше приложение.

Что означает "обрабатывать универсальную ссылку"? Могу ли я когда-либо открывать данный URL с помощью SFSafariViewController, WKWebView или UIWebView? Используется ли это только во время -[UIApplicationDelegate application:continueUserActivity:restorationHandler:], или есть ли время ожидания? Означает ли это, что мы никогда не сможем открыть URL-адрес в SFSafariViewController, WKWebView или UIWebView?

Ответ 1

Я не уверен, что полностью понимаю ваш вопрос.

Просто для того, чтобы осветить основы, я позволю Apple объяснить что универсальная ссылка:

Универсальные ссылки позволяют пользователям открывать ваше приложение, когда они нажимают ссылки на ваш сайт в виде WKWebView и UIWebView и страницы Safari, в дополнение к ссылкам, которые приводят к вызову openURL:, например, те, которые происходят в Mail, Messages и другие приложения.

Итак, представьте, что вы работаете над клиентом Twitter и просматриваете график, вы сталкиваетесь с твитом со следующей ссылкой на видео YouTube: https://youtu.be/ejQod8liXm0

Если вы нажмете его, так как это URL-адрес HTTP, вы ожидаете, что Safari откроет ссылку. Тем не менее, я думаю, что все разработчики iOS могут в значительной степени согласиться с тем, что родные приложения лучше, поэтому лучший пользовательский интерфейс для официального приложения YouTube для открытия видео strong > , даже от вашего стороннего клиента.

Это то, что позволяют "Универсальные ссылки"; если приложение YouTube регистрируется на iOS в качестве приложения, ответственного за обработку https://www.youtube.com (*) ссылок, всех в iOS-экосистеме если мы будем следовать правилам API. То же самое происходит, если вы запускаете веб-сайт и хотите, чтобы какой-либо из ваших содержимого запускал ваше официальное приложение iOS, если оно было установлено пользователем, или для запроса пользователя, если они хотели бы установить его для лучшего пользователя (и, конечно, помочь вашему бизнесу).

Итак, со всем этим в стороне, вернемся к исходному тексту:

Если вы создаете экземпляр объекта SFSafariViewController, WKWebView или UIWebView для обработки универсальной ссылки, iOS открывает ваш сайт в Safari вместо открытия вашего приложения. Однако, если пользователь удаляет универсальную ссылку из встроенного объекта SFSafariViewController, WKWebView или UIWebView, iOS открывает ваше приложение.

Это означает, что, если из вашего приложения ваш пользователь нажимает на универсальную ссылку на ваш контент (пример: http://www.your-company.com/foo), и вы не обнаруживаете это в своем коде приложения через регулярное выражение, например, и вместо этого создаете экземпляр SFSafariViewController, WKWebView или UIWebView, чтобы открыть его, как если бы это была регулярная ссылка на The New York Times или что-то еще, OS поймет, что вместо того, чтобы открывать это в своем приложении, вы хотите, чтобы Safari обрабатывал это для вас, Помните: цель Universal Links заключается в том, чтобы пользователь мог получить лучший опыт за счет того, что URL-адрес обрабатывается родным приложением, а не браузером.

Это то, что говорит первое предложение. Что касается второго, он устраняет потенциальный вопрос о последующих действиях: что, если пользователь нажимает на Universal Link на мой контент из встроенного браузера из другого приложения, которое не принадлежит мне? Затем в предложении говорится, ОС будет вести себя нормально: он откроет ваше приложение, соблюдая правила Universal Link.

TL; DR: вам нужно также обнаруживать универсальные ссылки на свой контент из вашего приложения, в коде и обрабатывать их. iOS не справится с этим для вас. Вместо этого, если вы сообщите ОС, чтобы открыть универсальную ссылку на контент вашего приложения во встроенном браузере из вашего приложения, она будет делать то, что указано.

EDIT: Если вам нужна помощь в решении вопроса о запросе SFSafariViewController или API -openURL:options:completitionHandler: для открытия URL-адреса, this ссылка должна помочь вам; Моя рекомендация состояла бы в том, чтобы сначала использовать -openURL:options:completitionHandler:, и если это не удастся, используйте SFSafariViewController или аналогичный.

Надеюсь, что это поможет, и я правильно понял ваш вопрос.

Ура! И Happy IOS 11 программирование!:)

Ответ 2

Я решил эту проблему с моим классом Swift 4 ниже. Он также использует встроенный браузер Safari, если это возможно. Вы можете использовать аналогичный метод и в вашем случае.

import UIKit
import SafariServices

class OpenLink {
    static func inAnyNativeWay(url: URL, dontPreferEmbeddedBrowser: Bool = false) { // OPEN AS UNIVERSAL LINK IF EXISTS else : EMBEDDED or EXTERNAL
        if #available(iOS 10.0, *) {
            // Try to open with owner universal link app
            UIApplication.shared.open(url, options: [UIApplication.OpenExternalURLOptionsKey.universalLinksOnly : true]) { (success) in
                if !success {
                    if dontPreferEmbeddedBrowser {
                        withRegularWay(url: url)
                    } else {
                        inAnyNativeBrowser(url: url)
                    }
                }
            }
        } else {
            if dontPreferEmbeddedBrowser {
                withRegularWay(url: url)
            } else {
                inAnyNativeBrowser(url: url)
            }
        }
    }
    private static func isItOkayToOpenUrlInSafariController(url: URL) -> Bool {
        return url.host != nil && (url.scheme == "http" || url.scheme == "https") //url.host!.contains("twitter.com") == false
    }
    static func inAnyNativeBrowser(url: URL) { // EMBEDDED or EXTERNAL BROWSER
        if isItOkayToOpenUrlInSafariController(url: url) {
            inEmbeddedSafariController(url: url)
        } else {
            withRegularWay(url: url)
        }
    }
    static func inEmbeddedSafariController(url: URL) { // EMBEDDED BROWSER ONLY
        let vc = SFSafariViewController(url: url, entersReaderIfAvailable: false)
        if #available(iOS 11.0, *) {
            vc.dismissButtonStyle = SFSafariViewController.DismissButtonStyle.close
        }
        mainViewControllerReference.present(vc, animated: true)
    }
    static func withRegularWay(url: URL) { // EXTERNAL BROWSER ONLY
        if #available(iOS 10.0, *) {
            UIApplication.shared.open(url, options: [UIApplication.OpenExternalURLOptionsKey(rawValue: "no"):"options"]) { (good) in
                if !good {
                    Logger.log(text: "There is no application on your device to open this link.")
                }
            }
        } else {
            UIApplication.shared.openURL(url)
        }
    }
}