我一直试图了解UIWebView缓存的工作原理.因为我的目标是能够管理UIWebView分配的内存(至少,尽可能多),以避免无限期地内存提升和App因此而被杀死.
后读 其他 计算器 问题和搜索 的 网站,我决定尝试NSURLCache sharedURLCache,但我无法弄清楚它是如何真正起作用.
我的测试场景是这样的:
我已经为iOS 5实现了一个测试应用程序,其中我有一个内部有UIWebView的视图.这个UiWebview将加载一个本地index.html文件,如下所示:
// Create an NSString from the local HTML file
NSString *fullURL = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory:@"www"];
NSURL *url = [NSURL fileURLWithPath:fullURL];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
// Load local HTML file
[self.webView loadRequest:requestObj];
Run Code Online (Sandbox Code Playgroud)
在这个index.html文件中,我有一个JS脚本,可以从Flickr下载JSON,最后一个图像上传到他们的公共源.每个图像都附加到列表中.整个过程每秒重复一次,直到我们从Feed中下载了1000张图像.看代码:
var nImg = 0;
function getData()
{
$.getJSON('http://api.flickr.com/services/feeds/photos_public.gne?format=json&jsoncallback=?', function(data)
{
var items = [];
$.each(data.items, function(i, image) {
items.push('<li id="' …Run Code Online (Sandbox Code Playgroud) 使用NSURLSession默认缓存,如何使特定URL的缓存无效?
我注意到NSURLCache的removeCachedResponseForRequest:方法,但这需要一个NSURLRequest对象,我没有原始请求.我是否需要在创建它们时存储它们,以便我可以将它们传回,removeCachedResponseForRequest:或者我可以创建一个具有相应URL的新URL,即使它没有相同的标题也将用作相应的URL.字段和其他属性作为原始?
在iOS 7中,我能够将共享URL缓存设置为子类,NSURLCache并且UIWebView我创建的任何s都会自动为每个请求使用该共享缓存.
// Set the URL cache and leave it set permanently
ExampleURLCache *cache = [[ExampleURLCache alloc] init];
[NSURLCache setSharedURLCache:cache];
Run Code Online (Sandbox Code Playgroud)
但是,现在在iOS 8中,似乎UIWebView从共享缓存中拉出并且cachedResponseForRequest永远不会被调用.
有没有人找到这个变化的文档,或者解决方法?
我的应用程序加载了一个非常大的webapp UIWebView.
我写了一个NSURLCache扩展名" LocalCache".
此LocalCache扩展程序拦截我的webapp加载,并从加密的本地应用程序包中提供所有请求的文件.该逻辑在NSURLCache's cachedResponseForRequest方法中实现.因此该应用程序在本地100%提供:
class LocalCache:NSURLCache {
override func cachedResponseForRequest( request: NSURLRequest) -> NSCachedURLResponse? {
if (request points to my domain) {
get file from bundle
decrypt it
return local copy
} else {
return super.cachedResponseForRequest(request)
}
}
}
NSURLCache.setSharedURLCache(LocalCache());
Run Code Online (Sandbox Code Playgroud)
我想将此功能移植到WKWebkit.我想知道是否有办法实现类似的东西,因为不幸的是,你可能知道,WKWebView不使用NSProtocol,NSUrl,NSUrlCache的Cocoa堆栈....使我当前的方法无用.
那么,可以用类似的东西完成WkWebView吗?
注意:UiWebView"认为"我的应用程序来自远程服务器的事实是应用程序的关键:如果我只是在本地加载应用程序,即.file://,有很多东西不起作用,例如,YouTube视频,因为youtube api抱怨" file://"不是批准的来源.所以WkWebView我正在寻找的解决方案必须与拦截缓存相关,而不是注入本地javascript.
CSURLCache旨在缓存资源以进行脱机浏览,因为NSURLCache只将数据存储在内存中.
如果cachedResponse在返回应用程序崩溃之前自动释放,如果没有,则只是泄漏对象.
任何可以照到这上面的光都会非常感激.
请注意stringByEncodingURLEntities是一种类别方法NSString.
@interface CSURLCache : NSURLCache {} @end
@implementation CSURLCache
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request
{
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[[[request URL] absoluteString] stringByEncodingURLEntities]];
if ([[NSFileManager defaultManager] fileExistsAtPath:path])
{
NSData *data = [[NSData alloc] initWithContentsOfFile:path];
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:[request URL]
MIMEType:nil
expectedContentLength:[data length]
textEncodingName:nil];
NSCachedURLResponse *cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:response
data:data];
[response release];
[data release];
return cachedResponse;
}
return nil;
}
@end
Run Code Online (Sandbox Code Playgroud)
更新:向Apple提交雷达后,似乎这是一个已知问题(雷达#7640470).
在 NSOperation 子类中,我使用以下代码从我们的服务器下载一个 xml 文件,然后对其进行解析:
NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:15];
NSData * receivedData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
Run Code Online (Sandbox Code Playgroud)
我第二次发出同样的请求,服务器返回一个 HTTP 304,缓存的响应数据存储在receivedData. 到现在为止还挺好。
我的问题:当设备离线时是否有可能获得相同的缓存响应?
我使用NSURLCache带AFNetworking.缓存工作正常,但无法检查是否实际从缓存中检索到响应.要检查缓存版本是否可用,我使用
[[NSURLCache sharedURLCache] cachedResponseForRequest:_request];
Run Code Online (Sandbox Code Playgroud)
检查我的文件的缓存版本.
我的服务器正在发送以下标头:
Cache-Control:public, must-revalidate, max-age=0
ETag:"317a405bf9f69346c1f0438736a3d02e"
Run Code Online (Sandbox Code Playgroud)
这基本上应该确保缓存后的响应在下载后立即失效.但是,cachedResponseForRequest:仍然会将以前缓存的版本加载到磁盘上,即使它实际上已过期.
NSURLCache永不过期或我不发送正确的头,等?编辑
我也试过发送
Expires: "Mon, 27 May 2013 14:34:50 GMT"
Run Code Online (Sandbox Code Playgroud)
标头和响应仍然从缓存返回,即使它已经过期.我觉得这种感觉NSURLCache不正常......
我想为使用共享的方法编写单元测试NSURLSession,特别是NSURLSessionDataTask下载数据.基本上,我希望目标方法接收模拟响应/数据,而无需互联网连接.
嘲笑这些组件的不那么不引人注目的方式是什么?我正在考虑NSURLCache使用模拟响应和数据填充,但我觉得这假设了太多的工作方式NSURLSession和NSURLSessionDataTask工作.还有其他建议吗?
当我测试时NSURLCache,我得到了"301PermMove",这是我的代码
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSURL *url = [NSURL URLWithString:@"https://www.github.com"];
NSURLRequest *urlRequest = [[NSURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:10];
NSURLCache *shareCache = [NSURLCache sharedURLCache];
NSCachedURLResponse *resp = [shareCache cachedResponseForRequest:urlRequest];
NSLog(@"cache data:%@",[[NSString alloc]initWithData:resp.data encoding:NSUTF8StringEncoding]);
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
NSLog(@"data:%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
}
Run Code Online (Sandbox Code Playgroud)
第一次触摸:缓存数据为零,第二次触摸:缓存数据为301PermMove.为什么?我不知道.
我正在尝试将URLRequest中的数据/响应注入我的缓存中的另一个 URLRequest.
这只是一个示例代码.它已准备好被转储到一个项目中.
我正在尝试做的是使用从我的landscapeURLString网络请求中检索到的响应+数据...存储到我的会话缓存中以获取我的lizardURLString请求.
import UIKit
class ViewController: UIViewController {
lazy var defaultSession : URLSession = {
let urlCache = URLCache(memoryCapacity: 500 * 1024 * 1024, diskCapacity: 500 * 1024 * 1024, diskPath: "something")
let configuration = URLSessionConfiguration.default
configuration.urlCache = urlCache
let session = URLSession(configuration: configuration)
return session
}()
lazy var downloadLizzardbutton : UIButton = {
let btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.setTitle("download lizard image OFFLINE", for: .normal)
btn.backgroundColor = .blue
btn.addTarget(self, …Run Code Online (Sandbox Code Playgroud) nsurlcache ×10
ios ×6
caching ×3
nsurlsession ×3
ios8 ×2
uiwebview ×2
afnetworking ×1
autorelease ×1
cocoa ×1
etag ×1
http ×1
instruments ×1
ios4 ×1
ios5 ×1
macos ×1
nscache ×1
objective-c ×1
swift ×1
unit-testing ×1
wkwebview ×1