Как открыть связанный pdf с turbolinks-ios
Мне интересно, как открыть связанный pdf-файл с платформой turbolinks-ios в iOS.
В настоящее время я испытываю проблему, заключающуюся в том, что когда страница турболинков ссылается на PDF-файл или другой файл, ссылка открывается в Safari, а не во встроенном представлении.
Фон
Библиотека turbolinks-5 вместе с платформой turbolinks-ios обеспечивают способ подключения веб-приложения к встроенным контроллерам навигации соответствующего мобильного приложения.
Скриншот взят с турболинков README.
Желаемое поведение
При нажатии на ссылку, которая ссылается на pdf, контроллер текущего представления должен быть перенесен в текущий контроллер навигации, чтобы пользователь мог прочитать pdf и легко вернуться к индексу документа.
Наблюдаемое поведение
Связанный PDF открывается в сафари, а не в приложении. К сожалению, сафари снова просит аутентификацию. Кроме того, пользователь должен покинуть приложение.
1 ответ
Перехватить нажатие ссылки PDF
Для ссылки на файл PDF, didProposeVisitToURL
механизм не запускается для делегата сеанса. Таким образом, никто не может решить оттуда, как обращаться со связанным pdf.
Вместо этого можно было перехватить щелчок по ссылке, став делегатом навигации веб-представления turbolinks, как показано в README:
extension NavigationController: SessionDelegate {
// ...
func sessionDidLoadWebView(session: Session) {
session.webView.navigationDelegate = self
}
}
extension NavigationController: WKNavigationDelegate {
func webView(webView: WKWebView,
decidePolicyForNavigationAction navigationAction: WKNavigationAction,
decisionHandler: (WKNavigationActionPolicy) -> ()) {
// This method is called whenever the webView within the
// visitableView attempts a navigation action. By default, the
// navigation has to be cancelled, since when clicking a
// turbolinks link, the content is shown in a **new**
// visitableView.
//
// But there are exceptions: When clicking on a PDF, which
// is not handled by turbolinks, we have to handle showing
// the pdf manually.
//
// We can't just allow the navigation since this would not
// create a new visitable controller, i.e. there would be
// no back button to the documents index. Therefore, we have
// to create a new view controller manually.
let url = navigationAction.request.URL!
if url.pathExtension == "pdf" {
presentPdfViewController(url)
}
decisionHandler(WKNavigationActionPolicy.Cancel)
}
}
Представьте контроллер просмотра PDF
Аналогично представлению доступного просмотра, как показано в демонстрационном приложении turbolinks-ios, представьте контроллер представления PDF:
extension NavigationController {
func presentPdfViewController(url: NSURL) {
let pdfViewController = PdfViewController(URL: url)
pushViewController(pdfViewController, animated: true)
}
}
Или, если вы хотите показать и другие типы файлов, позвоните fileViewController
скорее, чем pdfViewController
,
PdfViewController
Новый контроллер представления наследуется от VisitableViewController от turbolinks, чтобы использовать инициализацию по URL.
class PdfViewController: FileViewController {
}
class FileViewController: Turbolinks.VisitableViewController {
lazy var fileView: WKWebView = {
return WKWebView(frame: CGRectZero)
}()
lazy var filename: String? = {
return self.visitableURL?.pathComponents?.last
}()
override func viewDidLoad() {
view.addSubview(fileView)
fileView.bindFrameToSuperviewBounds() // https://stackru.com/a/32824659/2066546
self.title = filename // https://stackru.com/a/39022302/2066546
fileView.loadRequest(NSURLRequest(URL: visitableURL))
}
}
Чтобы получить веб-вид на правильный размер, я использовал bindFrameToSuperviewBounds
как показано в этом ответе stackru, но я уверен, что есть другие методы.
Необязательно: обмен файлами cookie
Если для загрузки pdf требуется проверка подлинности, удобно делиться файлами cookie с веб-представлением turbolinks-ios, как описано в README.
Например, создать webViewConfiguration
который может быть передан pdfViewController
:
extension NavigationController {
let webViewProcessPool = WKProcessPool()
lazy var webViewConfiguration: WKWebViewConfiguration = {
let configuration = WKWebViewConfiguration()
configuration.processPool = self.webViewProcessPool
// ...
return configuration
}()
lazy var session: Session = {
let session = Session(webViewConfiguration: self.webViewConfiguration)
session.delegate = self
return session
}()
}
Такой же webViewConfiguration
должен быть передан в session
(показано выше), а также для нового контроллера просмотра PDF.
extension NavigationController {
func presentPdfViewController(url: NSURL) {
let pdfViewController = PdfViewController(URL: url)
pdfViewController.webViewConfiguration = self.webViewConfiguration
pushViewController(pdfViewController, animated: true)
}
}
class FileViewController: Turbolinks.VisitableViewController {
var webViewConfiguration: WKWebViewConfiguration
lazy var fileView: WKWebView = {
return WKWebView(frame: CGRectZero, configuration: self.webViewConfiguration)
}()
// ...
}