2011-02-10 4 views

ответ

25

Можно загрузить NSData из URL-адреса и преобразовать его в изображение и придерживаться этого в представлении изображения, но это очень плохая идея, поскольку он включает в себя загрузку синхронного URL-адреса в основном потоке. Это закроет пользовательский интерфейс и, возможно, заставит пользователя подумать, что ваше приложение потерпело крах, если изображение не загружается очень быстро.

Редактировать: Для того, чтобы уточнить, оригинальный вопрос смотрит на меня, как плакат хочет сказать что-то вдоль линий

imageView.image = [UIImage imageWithContentsOfURL:theURL]; 

Отсюда мой ответ. Эквивалент можно выполнить через NSData, но это плохая идея. Вместо этого изображение должно быть загружено асинхронно с использованием NSURLConnection и только после полной загрузки, если оно будет преобразовано в UIImage и присвоено представлению изображения.

+1

+1 Как вы говорите, это, безусловно, плохая идея. Тем не менее, вы можете использовать образ заполнителя, а затем запустить фоновый вывод NSURLConnection. –

+0

Хорошо. как насчет многопоточности? Существуют ли какие-либо другие способы разработки динамического приложения, которое, как мне кажется, должно читаться в plist, и использовать ссылки в этом списке, например. прочитать изображение и отобразить его. Я не хочу обновлять приложение каждый раз, когда сайт обновляется. – jarryd

+1

@alJaree Как я уже сказал, вы можете использовать образ заполнителя и загружать «текущее» изображение асинхронно через NSURLConnection. Есть хороший пример того, как использовать NSURLConnection в [Руководство по программированию системы загрузки URL-адресов] (http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html) –

2

К сожалению, эта функция не доступна в качестве этого письма ... вместо этого вы должны будете реализовать функциональность самостоятельно путем:

  1. загрузив данные изображения
  2. Сохранение его или кэширование его где-то (БД или файловой системы), а затем
  3. Установка UIImaveView к сохраненной структуре

к счастью, вам не придется ломать голову приходит с указанной функцией как Apple предоставляет an example that does exactly that как часть своих образцов кода.

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

+0

Спасибо. Он упоминает rss.разве этот пример не читается в rss-потоке и не захватывает изображения? У меня уже есть эта функция в приложении, теперь я пытаюсь читать в структуре данных из URL-адреса сайта. Используйте эту структуру в своем приложении, чтобы получить количество изображений, а затем возьмите URL-адрес для каждого изображения и в зависимости от его соответствующего номера в plist, установите определенный UIImageView с изображением, таким образом я могу динамически обновлять приложение и заменять изображений. – jarryd

+0

Это просто часть функциональности примера приложения, но там, где вы хотите обратить внимание на ур, это та часть, где она берет URL-адрес изображений и извлекает их (для этого и предназначен класс IconDownloader) ... этот образец идет один раз шаг, так как он также показывает вам, как использовать этот класс из табличного представления таким образом, который является эффективным. – samiq

2

EGOImageLoading

EGOImageView* imageView = [[EGOImageView alloc] initWithPlaceholderImage:[UIImage imageNamed:@"placeholder.png"]]; 
imageView.frame = CGRectMake(0.0f, 0.0f, 36.0f, 36.0f); 

//show the placeholder image instantly 
[self.anyView addSubview:imageView]; 
[imageView release] //if you want 

//load the image from url asynchronously with caching automagically 
imageView.imageURL = [NSURL URLWithString:photoURL]; 

Если вы хотите больше, то есть делегат для обработки действий после загрузки

@protocol EGOImageViewDelegate<NSObject> 
@optional 
- (void)imageViewLoadedImage:(EGOImageView*)imageView; 
- (void)imageViewFailedToLoadImage:(EGOImageView*)imageView error:(NSError*)error; 
@end 
55
NSString *ImageURL = @"YourURLHere"; 
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]]; 
imageView.image = [UIImage imageWithData:imageData]; 
+36

Это синхронно и будет блокировать основной поток при извлечении изображения. Очень плохая идея. – svth

+0

Используйте HJCache (можно найти в github), если у вас есть длинные данные. избегайте зависания пользовательского интерфейса. –

+0

Вы можете легко сделать его асинхронным. Но это самая элегантная вещь. –

23

Я использую https://github.com/rs/SDWebImage который красиво оформленную библиотеку, которая имеет параметры, чтобы поместить образ заполнителя, будь то в память или кэш диска, или использовать загрузчик независимо от UIImageView.

Я пытался это сделать сам, но библиотека отняла всю боль.

Все, что вам нужно сделать, это написать код ниже для Вашего случая:

#import "UIImageView+WebCache.h" 

[imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder.png"]]; 

Работал как шарм для меня.

+4

Я всегда предпочитаю писать свой собственный код, но всего за 5 минут работы плавность и скорость, которые я получил от этой библиотеки, впечатляют. Подробное объяснение установки тоже помогло. – Yahel

2

Другой вариант - TTImageView из библиотеки Three20, которая обрабатывает асинхронную загрузку изображения. Управление отлично работает. Однако недостатком является то, что вам приходится иметь дело с кошмаром установки Three20 (который тогда почти невозможно полностью удалить).

0

Заканчивать образец кода от Apple для LazyTableImages - IconDownloader

Этот пример демонстрирует многоступенчатый подход к загрузке и отображающее UITableView. Он начинается с загрузки соответствующего текста из RSS-канала, поэтому таблица может загружаться как можно быстрее, а затем загружает изображения для каждой строки асинхронно, поэтому пользовательский интерфейс более отзывчивый.

LazyTableImages provided by Apple

11

Если вы хотите отобразить изображение из Url в ImageView, а также хотите сохранить этот файл в кэше оптимизируют для взаимодействия с сервером это поможет вам просто передать свой объект ImageView и струнный Url этому функция

-(void)downloadingServerImageFromUrl:(UIImageView*)imgView AndUrl:(NSString*)strUrl{ 


strUrl = [strUrl encodeUrl]; 

NSString* theFileName = [NSString stringWithFormat:@"%@.png",[[strUrl lastPathComponent] stringByDeletingPathExtension]]; 


NSFileManager *fileManager =[NSFileManager defaultManager]; 
NSString *fileName = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"tmp/%@",theFileName]]; 



imgView.backgroundColor = [UIColor darkGrayColor]; 
UIActivityIndicatorView *actView = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; 
[imgView addSubview:actView]; 
[actView startAnimating]; 
CGSize boundsSize = imgView.bounds.size; 
CGRect frameToCenter = actView.frame; 
// center horizontally 
if (frameToCenter.size.width < boundsSize.width) 
    frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width)/2; 
else 
    frameToCenter.origin.x = 0; 

// center vertically 
if (frameToCenter.size.height < boundsSize.height) 
    frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height)/2; 
else 
    frameToCenter.origin.y = 0; 

actView.frame = frameToCenter; 


dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
dispatch_async(queue, ^{ 

    NSData *dataFromFile = nil; 
    NSData *dataFromUrl = nil; 

    dataFromFile = [fileManager contentsAtPath:fileName]; 
    if(dataFromFile==nil){ 
     dataFromUrl=[[[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:strUrl]] autorelease];      
    } 

    dispatch_sync(dispatch_get_main_queue(), ^{ 

     if(dataFromFile!=nil){ 
      imgView.image = [UIImage imageWithData:dataFromFile]; 
     }else if(dataFromUrl!=nil){ 
      imgView.image = [UIImage imageWithData:dataFromUrl]; 
      NSString *fileName = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"tmp/%@",theFileName]]; 

      BOOL filecreationSuccess = [fileManager createFileAtPath:fileName contents:dataFromUrl attributes:nil];  
      if(filecreationSuccess == NO){ 
       NSLog(@"Failed to create the html file"); 
      } 

     }else{ 
      imgView.image = [UIImage imageNamed:@"NO_Image.png"]; 
     } 
     [actView removeFromSuperview]; 
     [actView release]; 
     [imgView setBackgroundColor:[UIColor clearColor]]; 
    }); 
}); 


} 
53

для такой простой задачи я настоятельно рекомендую против интегрирующих проектов, таких как Three20, библиотека монстра и не очень просто встать и бежать.

Я бы вместо того, чтобы рекомендовать этот подход:

NSString *imageUrl = @"http://www.foo.com/myImage.jpg"; 
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 
    myImageView.image = [UIImage imageWithData:data]; 
}]; 

EDIT для Swift 3.0

let urlString = "http://www.foo.com/myImage.jpg" 
guard let url = URL(string: urlString) else { return } 
URLSession.shared.dataTask(with: url) { (data, response, error) in 
    if error != nil { 
     print("Failed fetching image:", error) 
     return 
    } 

    guard let response = response as? HTTPURLResponse, response.statusCode == 200 else { 
     print("Not a proper HTTPURLResponse or statusCode") 
     return 
    } 

    DispatchQueue.main.async { 
     self.myImageView.image = UIImage(data: data!) 
    } 
}.resume() 

* EDIT для Swift 2.0

let request = NSURLRequest(URL: NSURL(string: urlString)!) 

NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in 

    if error != nil { 
     print("Failed to load image for url: \(urlString), error: \(error?.description)") 
     return 
    } 

    guard let httpResponse = response as? NSHTTPURLResponse else { 
     print("Not an NSHTTPURLResponse from loading url: \(urlString)") 
     return 
    } 

    if httpResponse.statusCode != 200 { 
     print("Bad response statusCode: \(httpResponse.statusCode) while loading url: \(urlString)") 
     return 
    } 

    dispatch_async(dispatch_get_main_queue(), {() -> Void in 
     self.myImageView.image = UIImage(data: data!) 
    }) 

    }.resume() 
+1

'sendAsynchronousRequest: queue: completionHandler:' устарел в iOS 9, теперь используется '[NSURLSession dataTaskWithRequest: completionHandler:]' –

+0

Удивительный ответ работает с большим удовольствием. Единственное, что я хотел бы сказать, это «' guard let url = NSURL (string: urlString) else {return} '' ', а затем' '' let request = NSURLRequest (URL: url) '' 'как раз вовремя что строка URL неверна, чтобы избежать сбоев. – Steve

3

Вот обновленный ответ на лучший ответ, поскольку imageWithContentsOfURL больше не является методом UIImage. Вы должны будете использовать CIImage:

NSURL *url = [NSURL URLWithString:@"http://url_goes_here.com/logo.png"]; 
imageView.image = [UIImage imageWithCIImage:[CIImage imageWithContentsOfURL:url]]; 
0

использование AFNetworking категории UIImageView+AFNetworking.h

#import "UIImageView+AFNetworking.h 


[profileImageView setImageWithURL:[NSURL URLWithString:photoURL] placeholderImage:[UIImage imageNamed:@"placeholder"]]; 
Смежные вопросы