Ответ 1
NSURL *url = [NSURL URLWithString:@"http://example.com/image.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[[UIImage alloc] initWithData:data] autorelease];
Однако это не асинхронно.
Как загрузить изображение и превратить его в UIImage?
NSURL *url = [NSURL URLWithString:@"http://example.com/image.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[[UIImage alloc] initWithData:data] autorelease];
Однако это не асинхронно.
Вы должны помнить, что загрузка данных изображения с помощью кода примера, который вы предоставили в своем собственном ответе, блокирует основной поток до завершения загрузки. Это полезность no-no. Пользователи вашего приложения подумают, что ваше приложение не отвечает. Если вы хотите загрузить изображение, попробуйте NSURLConnection загрузить его асинхронно в своем потоке.
Прочитайте документацию Apple о загрузке async с NSURLConnection.
Когда загрузка будет завершена, вы можете создать экземпляр своего UIImage из объекта данных:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if (requestData)
{
self.image = [[[UIImage alloc] initWithData:requestData] autorelease];
}
}
Где requestData
и image
являются переменными экземпляра вашего содержащего класса, а image
является сохраненным свойством. Обязательно отпустите image
в подпрограмме dealloc
класса, например. используя self.image=nil;
.
Верно, что асинхронная загрузка является обязательной, но вы также можете достичь этого с помощью фонового вызова, если вам просто нужно простое решение.
[self performSelectorInBackground:@selector(loadImage) withObject:nil];
- (void)loadImage
{
NSURL * url = [NSURL URLWithString:@"http://.../....jpg"];
NSData * data = [NSData dataWithContentsOfURL:url];
UIImage * image = [UIImage imageWithData:data];
if (image)
{
// Success use the image
...
}
else
{
// Failed (load an error image?)
...
}
}
Здесь действительно хороший пример использования блоков: http://ios-blog.co.uk/iphone-development-tutorials/uiimage-from-url-%E2%80%93-simplified-using-blocks/
Основываясь на ответе @philfreo, я создал расширение NSURL в swift с использованием BrightFutures (для асинхронного обратного вызова:
extension NSURL{
func downloadImage() -> Future<UIImage, NSError>{
let promise = Promise<UIImage, NSError>()
Queue.global.async{
if let data = NSData(contentsOfURL: self){
if let image = UIImage(data: data){
promise.success(image)
return
}
}
promise.failure(NSError())
}
return promise.future
}
}
Это позволяет мне:
import BrightFutures
let someURL = ...;
someURL.downloadImage().onSuccess{ image in
// Do something with the UIImage
}
Простое синхронное расширение может выглядеть так:
extension NSURL{
func downloadImage() -> UIImage?{
if let data = NSData(contentsOfURL: self){
return UIImage(data: data){
}
return nil
}
}
Вы можете загрузить изображение в UIImageView
из URL-адреса без блокировки потока пользовательского интерфейса, просто используя dispatch_async
:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *url = [NSURL URLWithString:myURL];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage* image = [[UIImage alloc]initWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
[myImageView setImage:image];
});
});
Первый dispatch_async
используется для загрузки изображения из URL в фоновом режиме (без блокировки пользовательского интерфейса). Второй dispatch_async
используется для фактического ввода изображения, загруженного только в UIImageView
. Обратите внимание, что второй dispatch_async
предназначен для работы с основным потоком (потоком пользовательского интерфейса), который действительно является потоком, используемым для обновления пользовательского интерфейса.
Вот что ответ @philfreo выглядит как быстрый:
let urlString = "http://lorempixel.com/100/100/cats/"
let url = NSURL(string: urlString)!
let data = NSData(contentsOfURL: url)
let image = UIImage(data: data!)
Это работает на детской площадке: