如何使用turbolinks-ios

时间:2016-08-18 17:39:17

标签: ios swift turbolinks-ios

我想知道如何在iOS中使用turbolinks-ios框架打开链接的pdf文件。

目前,我遇到issue当turbolinks页面链接到pdf或其他文件时,该链接将在safari而不是嵌入视图中打开。

背景

turbolinks-5库与turbolinks-ios framework一起提供了一种将Web应用程序连接到相应移动应用程序的本机导航控制器的方法。

screenshot

屏幕截图取自turbolinks README

期望的行为

当点击引用pdf的链接时,应将seaparate视图控制器推送到当前导航控制器,以便用户可以阅读pdf并轻松导航回文档索引。

观察到的行为

链接的pdf在safari中打开,而不是在app中打开。不幸的是,safari再次请求身份验证。此外,用户必须离开该应用程序。

1 个答案:

答案 0 :(得分:3)

拦截点击pdf链接

对于pdf文件的链接,不会为会话委托触发didProposeVisitToURL mechanism。因此,无法从那里决定如何处理链接的pdf。

相反,可以通过成为turbolinks的网络视图导航委托shown in the 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视图控制器

与将可访问视图显示为shown in the turbolinks-ios demo application类似,提供pdf视图控制器:

extension NavigationController {
  func presentPdfViewController(url: NSURL) {
    let pdfViewController = PdfViewController(URL: url)
    pushViewController(pdfViewController, animated: true)
  }
}

或者,如果您还要显示其他文件类型,请将其命名为fileViewController而不是pdfViewController

PdfViewController

新的视图控制器继承了turbolinks'VisitableViewController,以便通过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://stackoverflow.com/a/32824659/2066546
    self.title = filename  // https://stackoverflow.com/a/39022302/2066546
    fileView.loadRequest(NSURLRequest(URL: visitableURL))
  }
}

为了使网页视图的大小正确,我使用了bindFrameToSuperviewBounds as shown in this stackoverflow answer,但我确定还有其他方法。

可选:共享cookie

如果加载pdf需要身份验证,则可以方便地将cookies与turbolinks-ios webview共享为described in the 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)
  }()

  // ...
}

演示

Screenshot