【问题标题】:How do I properly cache a NSURLRequest in swift?如何在 swift 中正确缓存 NSURLRequest?
【发布时间】:2015-12-11 04:22:25
【问题描述】:

如果有人问过这个问题,请原谅,但我进行了大量搜索,似乎无法迅速找到我正在寻找的答案。我有一个加载 PDF 文件的UIWebView,如果用户退出 WebView 并返回,我不希望用户再次经历繁琐的加载过程,那么如何缓存请求以加快加载速度?

这是我的代码:

var contentUrlPassedOn: String!

    override func viewDidLoad() {
        super.viewDidLoad()

        myWebView.delegate = self

        let url: NSURL! = NSURL(string: contentUrlPassedOn)

        myWebView.loadRequest(NSURLRequest(URL: url))
        var request: NSURLRequest
}

更新

我想要完成的工作可以在this video中看到

这是 Dropbox 的 iOS 应用示例。当其中一个文件已经加载时,每隔一次进入该文件(在本例中为 PDF)将是快速而简单的。这种方法正是我想要复制的。

有什么建议吗?

【问题讨论】:

  • 您可以将 NSURLRequest 的缓存策略更改为 NSURLRequestReturnCacheDataElseLoad 或 NSURLRequestReloadRevalidatingCacheData 以支持使用缓存数据。请参阅这篇 NSHipster 文章:nshipster.com/nsurlcache
  • 请检查我更新的问题,我添加了一个视频,准确地展示了我试图复制@DanNichols 的内容

标签: ios xcode swift caching uiwebview


【解决方案1】:

GIF

  1. 第一次进入这个ViewController,可以看到下载进度
  2. 然后第二次,它只是加载本地文件。所以它非常快

还有代码

class ViewController: UIViewController,NSURLSessionDownloadDelegate{
var sesson:NSURLSession!
var webview:UIWebView!
var progressView:UIProgressView!
override func viewDidLoad() {
    super.viewDidLoad()
    self.sesson =   NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: self, delegateQueue: NSOperationQueue.mainQueue())
    self.webview = UIWebView(frame: self.view.frame)
    self.view.addSubview(webview)
    let documentDir = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).first as! NSURL
    let pdfFilePath = documentDir.URLByAppendingPathComponent("Test.pdf");
    if NSFileManager.defaultManager().fileExistsAtPath(pdfFilePath.path!){
        let request = NSURLRequest(URL: pdfFilePath)
        webview.loadRequest(request)
    }else{
        progressView = UIProgressView(progressViewStyle: UIProgressViewStyle.Default);
        progressView.frame = CGRectMake(0, 0,200, 4)
        progressView.progress = 0
        progressView.progressTintColor = UIColor.blueColor()
        progressView.center = self.view.center
        self.view.addSubview(progressView)
        let remoteURL = "https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.pdf"
        let request = NSURLRequest(URL: NSURL(string: remoteURL)!)
        let downloadTask = self.sesson.downloadTaskWithRequest(request)
        downloadTask.resume()
    }
    // Do any additional setup after loading the view, typically from a nib.
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
    if progressView != nil{
        progressView.removeFromSuperview()
    }
    let documentDir = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).first as! NSURL
    let pdfFilePath = documentDir.URLByAppendingPathComponent("Test.pdf");
    NSFileManager.defaultManager().moveItemAtURL(location, toURL: pdfFilePath, error: nil)
    let request = NSURLRequest(URL: pdfFilePath)
    self.webview.loadRequest(request)
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
    var curprogress = Float(totalBytesWritten)/Float(totalBytesExpectedToWrite)
    progressView.progress = curprogress
}
}

【讨论】:

  • 等待这是将文件从应用程序保存到计算机上还是只是将其缓存在应用程序中?
  • 将文件保存到应用沙箱。你看图,因为我拍了模拟器的截图
  • 它会一直存在,直到你用代码删除它,如果你想它是自动删除的,把它保存到沙箱的缓存目录中
  • 好吧,我只是不希望用户每次尝试重新输入他们刚刚进入的 PDF 时都必须经历整个负载,最好的选择是什么?跨度>
  • 请检查我更新的问题,我添加了一个视频,准确地展示了我试图复制的内容
【解决方案2】:

NSURLConnection(和 NSURLSession 的共享会话)使用共享缓存。您可以配置该缓存的策略以使用磁盘存储,但我模糊的回忆是 iOS 默认仅使用内存缓存。看看 NSURLCache 类,然后做 Swift 的等价物:

NSString *myPath = ... // some subdirectory in your app's caches directory
NSURLCache *cache = [[NSURLCache alloc] initWithCapacity:2048576 /* 2M */
                                            diskCapacity: 134217728 /* 128M */
                                                    path:myPath];
[NSURLCache setSharedURLCache:cache];

或其他,你可能会有更好的运气。

请注意,iOS 中的磁盘缓存仍然是临时的,并且可以被操作系统删除,但只能在您的应用未运行时删除(假设最近没有更改)。

类似

let cacheDirectory = NSSearchPathForDirectoriesInDomains(.CachesDirectory, .UserDomainMask, true)[0] as String
var dir = cacheDir.stringByAppendingFormat("/urlCache/")
var cache = NSURLCache(memoryCapacity: 2048576,
   diskCapacity: 134217728,
   path: dir)
NSURLCache.setSharedURLCache(cache)

但我对 Swift 不是很熟悉,所以我可能会弄错语法。

【讨论】:

  • 在您的应用开始打开网络视图之前,您通常会只执行一次,可能在您应用的 didFinishLaunching 方法或其他方法中。
  • 所以我所要做的就是调用它,它会将我的 webView 请求缓存到该子目录?
  • 应该,是的。至少我 认为 WebKit 使用共享的 NSURL 缓存。我不是百分百确定。它要么有帮助,要么没有。
  • 所以你能用我问题中的代码做一个小例子吗?
  • 完成了,虽然我对自己的 Swift 语法不太自信。
猜你喜欢
  • 2013-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多