Отображение изображений в uiwebview из записи основных данных

#objective-c #ios #core-data #uiwebview #uiimage

#objective-c #iOS #основные данные #uiwebview #uiimage

Вопрос:

Итак, у меня есть приложение, которое я написал для iPad, и я хотел бы иметь возможность разрешать пользователям вставлять изображения в свои документы, выбирая изображение из альбома или камеры. Все это отлично работает. Поскольку пользователь может хранить документ дольше, чем изображение в альбоме, я делаю его копию, немного уменьшаю масштаб и сохраняю в таблице core data, которая используется только для этой цели.

Я сохраняю изображение следующим образом:

 NSManagedObjectContext* moc=[(ActionNote3AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSString* imageName=[NSString stringWithFormat:@"img%lf.png",[NSDate  timeIntervalSinceReferenceDate]];
Image* anImage = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:moc];
anImage.imageName=imageName;
anImage.imageData=UIImagePNGRepresentation(theImage);
NSError* error=nil;
if(![moc save:amp;error]) {...
  

Я использую подкласс NSURLCache, как предложено в Cocoa With Love, и ovverride cachedResponseForRequest таким образом:

 - (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request {
    NSString *pathString = [[[request URL] absoluteString]lastPathComponent];
    NSData* data = [Image dataForImage:pathString];
    if (!data) {
        return [super cachedResponseForRequest:request];
    }

    NSURLResponse *response =[[[NSURLResponse alloc] 
                               initWithURL:[request URL] 
                               MIMEType:[NSString stringWithString:@"image/png"] 
                               expectedContentLength:[data length] 
                               textEncodingName:nil] 
                              autorelease];
    NSCachedURLResponse* cachedResponse =[[[NSCachedURLResponse alloc] initWithResponse:response data:data] autorelease];

    return cachedResponse;
}
  

Я также удостоверяюсь, что приложение использует подкласс NSURLCache, выполнив это в моем делегате приложения в didFinishLaunchingWithOptions:

 ANNSUrlCache* uCache=[[ANNSUrlCache alloc]init];
[NSURLCache setSharedURLCache:uCache];
  

Метод, который возвращает данные изображения из записи основных данных, выглядит следующим образом:

  (NSData*)dataForImage:(NSString *)name {
    NSData* retval=nil;
    NSManagedObjectContext* moc=[(ActionNote3AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];

    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Image" inManagedObjectContext:moc];
    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"imageName==%@", name];
[request setPredicate:predicate];

    NSError* error=nil;
    NSArray *array = [moc executeFetchRequest:request error:amp;error];

    if ([array count]>0) {
        retval=((Image*)[array objectAtIndex:0]).imageData;
    }

    return retval;
}
  

Чтобы вставить изображение в веб-представление, у меня есть html-тег img, где имя в src =»» связано с именем в таблице изображений. Цель приведенного выше кода NSURLCache — отслеживать имя, которое мы сохранили в таблице изображений, перехватывать его и отправлять фактические данные изображения для запрошенного изображения.

Когда я запускаю это, я вижу, что изображение запрашивается в моем подклассовом объекте NSURLCache. Это поиск правильной записи и возврат данных, как и должно быть. Тем не менее, я все еще получаю значок «Изображение не найдено» в моем uiwebview:

Изображение для изображения не найдено

Итак, Маркус (ниже) предложил, чтобы я не сохранял данные изображения в таблице основных данных. Поэтому я внес изменения, чтобы приспособиться к этому:

Сохранение изображения:

 NSString* iName=[NSString stringWithFormat:@"img%lf.png",[NSDate timeIntervalSinceReferenceDate]];
NSData* iData=UIImagePNGRepresentation(theImage);

NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
NSString* fullPathToFile = [documentsDirectory stringByAppendingPathComponent:iName];
[iData writeToFile:fullPathToFile atomically:NO];
  

Извлечение изображения:

 - (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request {
    NSString *pathString = [[[request URL] absoluteString]lastPathComponent];
    NSString* iPath = [Image pathForImage:pathString];
    if (!iPath) {
        return [super cachedResponseForRequest:request];
    }

    NSData* idata=[NSData dataWithContentsOfFile:iPath];

    NSURLResponse *response =[[[NSURLResponse alloc] 
                               initWithURL:[request URL] 
                               MIMEType:@"image/png" 
                               expectedContentLength:[idata length] 
                               textEncodingName:nil] 
                              autorelease];
    NSCachedURLResponse* cachedResponse =[[[NSCachedURLResponse alloc] initWithResponse:response data:idata] autorelease];

    return cachedResponse;
}
  

В режиме отладки я вижу, что idata загружается с соответствующими данными изображения.

И я все еще получаю изображение, которое не найдено! Очевидно, я делаю что-то не так. Я просто не знаю, что это такое.

Итак… Что я здесь делаю не так? Как я могу заставить это работать правильно?

Спасибо.

Комментарии:

1. И как вы пытаетесь получить изображение в UIWebView? Не вижу этого в вашем коде.

2. @Tom — я отредактировал, чтобы включить информацию об этом. В основном тег img, где имя в src — это имя, используемое в файле изображения. Тег img вставляется в HTML-код до того, как html попадет в UIWebView.

Ответ №1:

Я бы настоятельно рекомендовал вам не хранить двоичные данные в Core Data. Хранение двоичных данных в Core Data, особенно на устройстве iOS, вызывает серьезные проблемы с производительностью кэша.

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

Комментарии:

1. Я действительно пробовал это, на самом деле. Я отредактировал свой вопрос, чтобы включить детали кода. Я предполагаю, что я где-то сделал что-то глупое, потому что это все еще не работает. Спасибо.

2. Я не вижу ничего, что выскакивает. У вас есть тестовый проект для такого поведения? Я обнаружил, что тест превосходен по нескольким причинам: 1) Мы можем с ним поработать, 2) Он изолирует код, и вы обычно можете самостоятельно определить проблему, 3) Если это ошибка Apple, ваш радар уже готов 🙂

Ответ №2:

Оказывается, я слишком много думал об этом. Когда я пишу HTML, я просто записываю путь к изображению с помощью тега image. Работает как шарм.

Я хотел бы знать, почему решение, которое я изложил в своем вопросе, не сработало.

И я не сохранил изображения в таблице.