Как получить доступ к ресурсу изображения в каталоге активов из UIWebView (или WKWebView)

У нас есть локальный HTML-код для показа в UIWebView. И там мы хотим показать изображения, определенные в каталоге активов.

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

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

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

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


person barley    schedule 14.11.2014    source источник


Ответы (3)


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

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

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

person Alex Shaffer    schedule 04.02.2015

Есть способ получить доступ к ресурсу изображения в каталоге активов из 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
person Alexander    schedule 24.08.2016
comment
Внедрите свой собственный NSURLProtocol и верните оттуда соответствующий UIImage в каталог активов, как я понимаю. Очень интересная идея! Ко мне никогда не приходил. Однако очевидным недостатком является то, что это влияет на все приложение NSURLRequest и не очень практично для моего приложения и, вероятно, для большинства приложений :( Сказав это, спасибо за новую точку зрения! - person barley; 12.09.2016
comment
Для меня это вылетает в -stopLoading с -[ImageProtocol task]: unrecognized selector sent to instance 0x7ad68ab0, но просто комментирование строки исправляет это. Отличное решение для моего случая использования. Спасибо! - person Gereon; 26.10.2017
comment
@Gereon Вы правы. В моем исходном коде я загружал запросы с помощью NSURLSession, поэтому я использовал для этого задачу. Исправил ответ. - person Alexander; 30.10.2017

Один из способов сделать это - преобразовать изображение в base64 и ввести его в HTML.

if let base64 = UIImage(named: "myImage")?.pngData()?.base64EncodedString() {
    webView.loadHTMLString("<img src='data:application/png;base64,(base64)'/>", baseURL: nil)
}
person enigrify    schedule 11.12.2020
comment
Спасибо за ответ. Не могли бы вы отредактировать свой ответ на, включив в него объяснение кода? Это поможет будущим читателям лучше понять, что происходит, и особенно тем членам сообщества, которые плохо знакомы с языком и изо всех сил пытаются понять концепции. - person Jeremy Caney; 12.12.2020
comment
У меня есть изображение в активе, я хочу преобразовать его ‹a href=xyz.s3.us-east-2.amazonaws.com/ src = \ xyz.s3.us-east-2.amazonaws.com/ \ width = \ 200 \ height = \ 200 \› ‹/a› . Как я могу это сделать - person Dilip Tiwari; 23.04.2021