20

我可以毫无问题地创建 Safari 视图控制器:

let svc = SFSafariViewController(URL: NSURL(string: remote_url)!, entersReaderIfAvailable: true)
self.presentViewController(svc, animated: true, completion: nil)

在将视图控制器呈现给用户之前,有什么方法可以预加载 URL?

例如,我可以先在后台预加载 URL(网页内容),然后在用户点击某些内容后,我可以立即将内容显示在 Safari 视图控制器中。用户会觉得页面加载更快或即时。

PS 变通办法/黑客也是可以接受的。例如,使用缓存或在后台启动视图控制器等。

编辑:请仅考虑 SFSafariViewController。

4

5 回答 5

12

这是一个解决方案。显然,如果您立即单击按钮,您将看到加载。但基本上,我加载浏览器并将视图放在另一个视图后面,然后在另一个视图中放置一个按钮。

当您按下按钮时,浏览器被带到前面,已经加载。这里唯一的问题是我没有使用任何转换,但这至少是一种解决方案。

import UIKit
import SafariServices

class ViewController: UIViewController {
  var svc = SFSafariViewController(URL: NSURL(string: "https://microsoft.com/")!, entersReaderIfAvailable: true)
  var safariView:UIView?
  let containerView = UIView()
  let btn = UIButton()

  override func viewDidLoad() {
    super.viewDidLoad()
    //let tmpView = svc.view
    addChildViewController(svc)
    svc.didMoveToParentViewController(self)
    svc.view.frame = view.frame
    containerView.frame = view.frame
    containerView.backgroundColor = UIColor.redColor()
    safariView = svc.view
    view.addSubview(safariView!)
    view.addSubview(containerView)

    btn.setTitle("Webizer", forState: UIControlState.Normal)
    btn.titleLabel!.textColor = UIColor.blackColor()
    btn.addTarget(self, action: "buttonTouched:", forControlEvents: .TouchUpInside)
    btn.frame = CGRectMake(20, 50, 100, 100)
    containerView.addSubview(btn)

    view.sendSubviewToBack(safariView!)

    // Do any additional setup after loading the view, typically from a nib.
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }

  @IBAction func buttonTouched(sender: AnyObject) {
    view.bringSubviewToFront(safariView!)
    //self.presentViewController(svc, animated: true, completion: nil)
  }


}
于 2016-02-12T07:25:57.290 回答
4

遗憾的是,当前的SFSafariViewController. 我会鼓励向 Apple 提交雷达以添加对这种行为的支持,但就像其他人建议的那样,最好的选择是WKWebView在将其添加到层次结构之前使用并开始加载。

我从 Twitter 上发现了一个可爱的雷达,它实际上准确地提到了你的要求。我认为您可能会发现以下请求很有用:

高优先级: - 能够在实际向 SFSafariViewController 呈现 URL、URL 请求、HTML 数据或磁盘上的文件之前预热它我们将使用该预缓存网页打开 UIWebView(遗憾的是不是 WKWebView)。如果我们可以用所需的链接来加热一个 SFSafariViewController,这将消除我们的大量工作。

您可以在他们的实现中看到他们只是使用 UIWebView 缓存响应,因为 WKWebView 似乎有点混淆了缓存语义。唯一的风险是 UIWebView 可能会被弃用,正如您在他们的文档“在 iOS 8 及更高版本中运行的应用程序中,使用 WKWebView 类而不是使用 UIWebView”中看到的那样。

所以不幸的是,你似乎需要跳过很多圈才能让这一切顺利进行,所以你现在最好的选择就是纠缠苹果并欺骗 Twitter 的雷达。

于 2016-02-09T07:56:58.517 回答
2

您可以尝试使用 http 缓存,但我认为它不会起作用,因为 Safari 视图控制器作为一个单独的进程工作(可能与 Safari 相同),所以这就是它绕过 ATS 的原因。

我能想到这个工作的唯一方法是以某种方式强制用户的 Safari 加载它?openURL:或者添加到阅读列表中?这听起来不像是一个可行的解决方案。

您始终可以尝试自定义视图控制器的呈现,将其附加到视图层次结构,触发外观事件,但将其框架设置到CGRectMake(0,0,1,1)或附加到屏幕外的某个位置,然后等待一段时间并用正确的框架表示它。

于 2016-02-09T20:58:21.207 回答
1

您可以使用以下代码下载网页。并借助 svc let data:NSData? do { let weatherData = try NSData(contentsOfURL: NSURL(string: remote_url)!, options: NSDataReadingOptions()) data = weatherData print(weatherData) } catch { print(error) }

并在需要时在 svc 中加载它

于 2016-02-12T09:23:21.177 回答
0

虽然技术上可以使用上述解决方案来实现您的要求,但这可能无法通过 App Store 审查。根据SFSafariViewController 文档

根据 App Store Review Guidelines,此视图控制器必须用于向用户展示信息;控制器不能被其他视图或层隐藏或遮挡。此外,应用不得在未经用户知情和同意的情况下使用 SFSafariViewController 跟踪用户。

于 2020-05-08T02:43:07.423 回答