如何使用动态创建的HTML WebView

时间:2014-01-21 17:53:31

标签: cocoa webview

我有一个应用程序可以创建HTML页面并在WebView中显示它们。那部分效果很好。

我的应用程序具有允许用户查看不同数据的控件。我可以将新的HTML字符串加载到WebView中。再次,这很好。

我有两个相关的问题:首先,我动态创建的HTML页面包含对<img>标签中图像的引用,这些标签实际上是压缩的并存储在专有文件中。我可以根据请求将这些加载到某种Cocoa图像对象中,或者我可以将它们解压缩到一个文件中并允许WebView加载它们。后者可能很简单,但我正在寻找实现前者的方法。我想我需要以某种方式对webView:resource:willSendRequest:redirectResponse:fromDataSource:消息作出回应/做出反应,以便WebView一张图片。任何提示?

其次,如果用户选择了一个链接,我需要拦截链接的处理并自己处理。如果链接实际引用页面上的某个位置,我可能只是将用户滚动到同一页面上的某个位置,或者(更频繁地)我想要加载一个完全不同的页面 - 再次,由我的应用程序动态创建并加载为使用WebView的{​​{1}}字符串。我想简单地通知URL,以便我可以决定如何处理它(就像我在iOS中使用UIWebView一样),但我不确定最好/最简单的方法。

我把这些问题放在一起,因为可能有一种普遍的方式来看待我错过的整个问题。例如,似乎应该有一种方法来取代正常的页面加载过程,以便loadHtmlString:baseUrl:向我的应用程序询问它通常要发送到Web请求的字节数。我得到的印象是WebView做了自己的事情,只有建议我正在从网上加载页面/资源。我需要它来实际请求我的数据。

1 个答案:

答案 0 :(得分:2)

最好的方法是实现自己的NSURLProtocol子类,它可以返回您需要的资源。这样您就可以使用自己的内部URL,URL加载系统将通过调用NSURLProtocol子类上的方法来获取它们。

这样做非常容易;您需要实施+canInitWithRequest:来检查您的特殊网址方案,例如

+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
  NSString *scheme = [[request URL] scheme];
  return [scheme caseInsensitiveCompare:@"app"] == NSOrderedSame;
}

然后让您的-startLoading方法返回正确的数据,例如:

- (void)startLoading
{
  NSURLRequest *req = [self request];
  id<NSURLProtocolClient> client = [self client];
  NSCachedURLResponse *cachedResponse = [self cachedResponse];

  if (cachedResponse) {
    [client URLProtocol:self cachedResponseIsValid:cachedResponse];
    return;
  }

  // support app:blank
  if ([[[req URL] resourceSpecifier] isEqualToString:@"blank"]) {
    NSData *data = [NSData data];

    NSURLResponse *response
      = [[NSURLResponse alloc] initWithURL:[req URL]
                                  MIMEType:@"text/html"
                     expectedContentLength:[data length]
                          textEncodingName:@"UTF-8"];

    [client URLProtocol:self
     didReceiveResponse:response
     cacheStoragePolicy:NSURLCacheStorageNotAllowed];

    [client URLProtocol:self didLoadData:data];

    [client URLProtocolDidFinishLoading:self];
    return;
  }

  // Not found
  NSError *error = [NSError errorWithDomain:NSURLErrorDomain
                                       code:NSURLErrorFileDoesNotExist
                                   userInfo:nil];

  [client URLProtocol:self didFailWithError:error];
}