objective-c - UIWebView 使用本地镜像和 javascript 文件加载远程 html 页面

标签 objective-c ios uiwebview

我创建的应用程序将使用本地镜像和 javascript/css 文件在 UIWebView 上显示远程页面以加快加载速度。我想避免使用缓存,因为要使其正常工作,它必须首先加载所有内容。我正在网上搜索可能的解决方案。这是我所拥有的:

 NSURLRequest *urlrequest = [ [NSURLRequest alloc] initWithURL: [NSURL URLWithString:urlString] ];
    NSData *returnData = [ NSURLConnection sendSynchronousRequest:urlrequest returningResponse: nil error: nil ];
    NSString *HTMLData = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];


    NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
    resourcePath = [resourcePath stringByReplacingOccurrencesOfString:@"/" withString:@"//"];
    resourcePath = [resourcePath stringByReplacingOccurrencesOfString:@" " withString:@"%20"];

    [webView loadHTMLString:HTMLData baseURL:
    [NSURL URLWithString: 
     [NSString stringWithFormat:@"file:/%@//",resourcePath]
     ]];

urlString 已定义,我将文件移动到应用程序包中。

代码可以正常工作,因为我可以看到远程页面,但不存在图像或 javascript 文件。

最佳答案

我通过继承 NSURLCache 解决了这个问题。

首先,创建NSURLCache的继承

#import "VURLCache.h"
#import <MobileCoreServices/UTType.h>

@implementation VURLCache

-(NSString*)mimeTypeForExtension:(NSString*)ext
{
    NSAssert( ext, @"Extension cannot be nil" );
    NSString* mimeType = nil;

    CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
        (CFStringRef)ext, NULL);
    if( !UTI ) return nil;

    CFStringRef registeredType = UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType);
    if( !registeredType ) // check for edge case
    {
        if( [ext isEqualToString:@"m4v"] )
                mimeType = @"video/x-m4v";
        else if( [ext isEqualToString:@"m4p"] )
                mimeType = @"audio/x-m4p";
        // handle anything else here that you know is not registered
    } else {
        mimeType = NSMakeCollectable(registeredType);
    }

    CFRelease(UTI);
    return mimeType;
}

-(void)parseBundleURL:(NSURL*)url 
                 name:(NSString**)name 
                  ext:(NSString**)ext 
      bundleDirectory:(NSString**)bundleDirectory {

    NSString* path = [url path];
    NSUInteger nameStart = NSNotFound;
    // locate the last '/'
    NSRange pathStop = [path rangeOfString:@"/" options:NSBackwardsSearch];
    if( 0 == pathStop.location ) {
        nameStart = 1;
    } else if ( NSNotFound != pathStop.location ) {
        // there is a path
        nameStart = pathStop.location+1;
        NSRange pathRange = NSMakeRange(0, nameStart);
        *bundleDirectory = [path substringWithRange:pathRange];
    }

    NSRange fileRange = NSMakeRange(nameStart, path.length - nameStart);
    if( fileRange.length > 0 ) {
        NSRange extStop = [path rangeOfString:@"." options:0 range:fileRange];
        if( NSNotFound != extStop.location ) {
            NSUInteger sep = extStop.location;
            NSRange nameRange = 
                NSMakeRange( nameStart, sep - nameStart);
            *name = [path substringWithRange:nameRange];
            NSRange extRange = 
                NSMakeRange( sep+1, path.length -(sep+1));
            *ext = [path substringWithRange:extRange];
        }
    }
}

-(NSCachedURLResponse*)bundleResourceForRequest:(NSURLRequest *)request {

    NSURL* url = [request URL];
    NSString* name = nil;
    NSString* ext = nil;
    NSString* bundleDirectory = nil;
    NSString* path = nil;

    [self parseBundleURL:url name:&name ext:&ext bundleDirectory:&bundleDirectory];

    if( name && ext ) {
        NSBundle* bundle = [NSBundle mainBundle];
        if( nil == bundleDirectory ) {
            path = [bundle pathForResource:name ofType:ext];
        } else {
            path = [bundle pathForResource:name ofType:ext inDirectory:bundleDirectory];
        }
    }

    NSCachedURLResponse* rep = nil;

    if( path ) {
        NSData* content = [NSData dataWithContentsOfFile:path];
        NSString* mime = [self mimeTypeForExtension:ext];
        NSString* encoding = nil;
        NSURLResponse* response = 
            [[NSURLResponse alloc] 
                    initWithURL:request.URL 
                       MIMEType:mime 
          expectedContentLength:[content length] 
               textEncodingName:encoding];
        rep = [[NSCachedURLResponse alloc] initWithResponse:response data:content];
    }

    return rep;
}

#pragma mark NSURLCache

-(NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request {
    NSURL* url = [request URL];
    if( [[url absoluteString] hasPrefix:VBUNDLE_URL_PREFIX] ) {
        return [self bundleResourceForRequest:request];
    }
    return [super cachedResponseForRequest: request];   
}

@end

然后,替换app delegate中默认的NSURLCache

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *docDir = [paths objectAtIndex:0];
NSString *path =  docDir; // the path to the cache file
NSUInteger discCapacity = 0;
NSUInteger memoryCapacity = 5120*1024;

VURLCache *cache = [[VURLCache alloc] initWithMemoryCapacity:memoryCapacity diskCapacity:discCapacity diskPath:path];
[NSURLCache setSharedURLCache:cache];
[cache release];

然后,您可以在您的应用程序包中加载文件。

例如,

这将显示您的应用程序图标。 你也可以用它加载 css。

关于objective-c - UIWebView 使用本地镜像和 javascript 文件加载远程 html 页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4881175/

相关文章:

iphone - 更早地检测有问题的 XIB View

ios - 为什么 UIWebView 中的谷歌搜索结果没有触发 webViewDidFinishLoad?

ios - 如何在 WKWebView 上的指定位置获取消息?

objective-c - 无法弄清楚 'warning: incompatible Objective-C types'

objective-c - 如何在 block 中修改 ObjC 方法的参数?

iOS 7.1 拥有比文档中列出的更多的 CoreImage 滤镜(例如 CIBumpDistortion 和 CIBumpDistortionLinear)。我们可以使用它们吗?

ios - 条件绑定(bind)的初始化程序必须具有 Optional 类型,而不是 'UIView'

objective-c - UIWebView 不打开 ms word (doc) 和 ms excel (xls) 文件

ios - ScrollView 理解

Objective-C 2.0 在 GNUstep 中不工作