【问题标题】:How to access image resource in asset catalog from UIWebView (or WKWebView)如何从 UIWebView(或 WKWebView)访问资产目录中的图像资源
【发布时间】:2015-01-11 07:11:09
【问题描述】:

我们有一个本地 html 可以在 UIWebView 中显示。在那里,我们想要显示在 Asset Catalog 中定义的图像。

我知道,如果我们将图像放在主包中,我们可以做类似的事情。代码 sn-p 将是这样的。

webView.loadHTMLString("<img src='target_image.png'/>", baseURL: NSBundle.mainBundle().bundleURL)

但是,如果 png 文件打包在资产目录中,我不确定我可以为“target_image.png”指定什么。 (此外,我们希望指定 pdf 以利用 Xcode 6 中的矢量图像支持)

有人知道如何实现吗?

【问题讨论】:

    标签: ios uiwebview asset-catalog


    【解决方案1】:

    由于资产目录作为单个文件存储在捆绑包中,因此无法获取单个资产的 URL。

    最简单的解决方案是不对您将在 Web 视图中显示的图像使用资产目录。

    如果将图像保留在资产目录中是必不可少的,那么您唯一的选择是将所需资产“解压缩”到应用程序包的文档目录中的不同文件中,然后引用这些文件。

    【讨论】:

      【解决方案2】:

      有一种方法可以从 UIWebView 访问资产目录中的图像资源。 您应该创建 NSUrlProtocol 子类,注册您的新协议并手动响应 WebView 图像请求。

      @interface AppDelegate : UIResponder <UIApplicationDelegate>
      @end
      
      @implementation AppDelegate
          - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
              [NSURLProtocol registerClass:[ImageProtocol class]];    
              //... other code
              return YES;
          }
      @end
      
      @interface ImageProtocol : NSURLProtocol
      @end
      
      @implementation ImageProtocol
      
          + (BOOL)canInitWithRequest:(NSURLRequest *)request {
              NSString *imgName = (NSString *)[[request.URL.absoluteString componentsSeparatedByString:@"/"] lastObject];
              AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
              NSLog(@"imgName = %@",imgName);
              if ([UIImage imageNamed:imgName] != nil) {// or check for explicit name "target_image.png"
                  return YES;
              }
              return NO;
          }
      
          + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
              return request;
          }
      
          + (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b{
              return [super requestIsCacheEquivalent:a toRequest:b];
          }
      
          - (void)startLoading {
              NSString *imgName = (NSString *)[[self.request.URL.absoluteString componentsSeparatedByString:@"/"] lastObject];
              UIImage *img = [UIImage imageNamed:imgName];
              NSString *mimeType = @"image/png";
              @try {
                  NSData *imageData = nil;
      
                  if ([imgName hasSuffix:@".png"]) {
                      imageData = UIImagePNGRepresentation(img);
                  } else if ([imgName hasSuffix:@".jpg"]) {
                      imageData = UIImageJPEGRepresentation(img, 1);
                      mimeType = @"image/jpg";
                  }
      
                  NSString *encoding = @"utf-8";
                  NSURLResponse *response = [[NSURLResponse alloc] initWithURL:self.request.URL
                                                              MIMEType:mimeType
                                                 expectedContentLength:imageData.length
                                                      textEncodingName:encoding];
      
                  [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
                  [self.client URLProtocol:self didLoadData:imageData];
                  [self.client URLProtocolDidFinishLoading:self];
              } @catch (NSException *exception) {
                  NSError *err = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorResourceUnavailable userInfo:nil];
                  [self.client URLProtocol:self didFailWithError:err];
                  NSLog(@"%@",exception.debugDescription);
              }
          }
      
          - (void)stopLoading {
          // do nothing
          }
      
          - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
              [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
          }
      
          - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
          [self.client URLProtocol:self didLoadData:data];
          }
      
          - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
              [self.client URLProtocolDidFinishLoading:self];
          }
      
          - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
              [self.client URLProtocol:self didFailWithError:error];
          }
      
      @end
      

      【讨论】:

      • 实现你自己的NSURLProtocol 并从那里返回资产目录中相应的 UIImage,我明白了。这是非常有趣的想法!从来没有来找我。但是,明显的缺点是它会影响整个 NSURLRequest 应用程序,并且对于我的应用程序以及可能大多数应用程序来说不是很实用:( 话虽如此,感谢您提供新的视角!
      • 对我来说,这在-stopLoading-[ImageProtocol task]: unrecognized selector sent to instance 0x7ad68ab0 中崩溃,但只需评论该行即可修复它。我的用例的绝佳解决方案。谢谢!
      • @Gereon 你是对的。在我的原始代码中,我使用 NSURLSession 加载了请求,因此我使用了任务。修正了答案。
      【解决方案3】:

      一种方法是将图像转换为base64 并将其输入到 HTML 中。

      if let base64 = UIImage(named: "myImage")?.pngData()?.base64EncodedString() {
          webView.loadHTMLString("<img src='data:application/png;base64,(base64)'/>", baseURL: nil)
      }
      

      【讨论】:

      • 感谢您提供答案。您能否编辑您的答案以包括对您的代码的解释?这将有助于未来的读者更好地了解正在发生的事情,尤其是那些刚接触该语言并难以理解概念的社区成员。
      • 我在资产中有一张图片,我想转换它 "xyz.s3.us-east-2.amazonaws.com/…src=\"xyz.s3.us-east-2.amazonaws.com/…\" width= \"200\" height= \"200\ "> . 我该怎么做
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-18
      • 2013-09-28
      • 1970-01-01
      相关资源
      最近更新 更多