#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. Работает как шарм.
Я хотел бы знать, почему решение, которое я изложил в своем вопросе, не сработало.
И я не сохранил изображения в таблице.