2014-11-14 2 views
11

У нас есть локальный html, который будет отображаться в UIWebView. И там мы хотим показать изображения, которые определены в Каталоге активов.Как получить доступ к ресурсу изображений в каталоге активов из UIWebView (или WKWebView)

Я знаю, что мы можем сделать подобное, если бы у нас было изображение в основном комплекте. Этот фрагмент кода будет таким.

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

Однако я не уверен, что я могу указать на «target_image.png», если файл PNG упакован в каталоге активов. (Кроме того, мы хотим указать pdf, чтобы воспользоваться поддержкой векторного изображения в Xcode 6)

Кто-нибудь знает, как это достичь?

ответ

14

Поскольку каталог активов хранится в комплекте как один файл, невозможно получить URL-адрес для уникального актива.

Простейшим решением является НЕ использовать каталог активов для изображений, которые вы покажете в веб-представлении.

Если сохранение изображений в каталоге активов имеет важное значение, единственным вариантом является «распаковать» требуемый актив (ы) в отдельные файлы в каталог документов пакета приложений, а затем ссылаться на эти файлы.

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 
+0

Внесите свой собственный 'NSURLProtocol' и верните соответствующий UIImage в каталог активов оттуда, я вижу. Это очень интересная идея! Никогда не приходил ко мне. Однако очевидным недостатком является то, что он влияет на приложение NSURLRequest и не очень практичен для моего приложения и, вероятно, для большинства приложений :( Сказав это, спасибо за новую перспективу! – barley

+0

Для меня это аварийно завершается в '-stopLoading' с '- [ImageProtocol task]: непризнанный селектор, отправленный в экземпляр 0x7ad68ab0', но просто комментируя строку. Это отличное решение для моего использования. Спасибо! – Gereon

+1

@Gereon Вы правы. В моем исходном коде я загрузил запросы с помощью NSURLSession поэтому я использовал для этого задачу. Исправлен ответ. – Alexander