【发布时间】:2011-02-10 20:54:24
【问题描述】:
是否可以读取图像的 url 并将 UIImageView 设置为该 url 处的图像?
【问题讨论】:
标签: iphone uiimageview
是否可以读取图像的 url 并将 UIImageView 设置为该 url 处的图像?
【问题讨论】:
标签: iphone uiimageview
对于如此简单的任务,我强烈建议不要集成诸如 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];
}];
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()
*为 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()
【讨论】:
sendAsynchronousRequest:queue:completionHandler: 在 iOS 9 中已弃用,现在使用 [NSURLSession dataTaskWithRequest:completionHandler:]
guard let url = NSURL(string: urlString) else {return} 然后let request = NSURLRequest(URL: url) 只是因为网址字符串格式错误以避免崩溃。
NSString *ImageURL = @"YourURLHere";
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
imageView.image = [UIImage imageWithData:imageData];
【讨论】:
可以从 URL 加载 NSData 并将其转换为图像并将其粘贴在图像视图中,但这是一个非常糟糕的主意,因为它涉及在主线程上执行同步 URL 下载。这将锁定 UI,如果图像下载速度不快,可能会导致用户认为您的应用已崩溃。
编辑:澄清一下,在我看来,最初的问题就像发帖人想说的那样
imageView.image = [UIImage imageWithContentsOfURL:theURL];
因此我的回答。可以通过 NSData 来做同样的事情,但这是个坏主意。相反,应该使用 NSURLConnection 异步下载图像,并且只有在完全下载后才能将其转换为 UIImage 并分配给图像视图。
【讨论】:
我正在使用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"]];
对我来说就像一个魅力。
【讨论】:
如果您想在 ImageView 中显示来自 Url 的图像,并且还想将此图像保存在缓存中以优化服务器交互,这将有助于您只需将您的 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]];
});
});
}
【讨论】:
这是最佳答案的更新答案,因为 imageWithContentsOfURL 不再是 UIImage 的方法。你必须使用 CIImage:
NSURL *url = [NSURL URLWithString:@"http://url_goes_here.com/logo.png"];
imageView.image = [UIImage imageWithCIImage:[CIImage imageWithContentsOfURL:url]];
【讨论】:
不幸的是,此功能在撰写本文时不可用...相反,您必须自己实现该功能:
幸运的是,由于 Apple 提供了 an example that does exactly that 作为其代码示例的一部分,因此您不必为上述功能而伤脑筋。
按照代码进行操作,我相信您将能够满足您的需求。
【讨论】:
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
【讨论】:
UIImageView如何支持它的代码?
另一个选项是 Three20 库中的 TTImageView,它处理图像的异步加载。控制效果很好。然而,缺点是您必须面对安装 Three20 的噩梦(这几乎不可能完全移除)。
【讨论】:
使用AFNetworking 类别UIImageView+AFNetworking.h
#import "UIImageView+AFNetworking.h
[profileImageView setImageWithURL:[NSURL URLWithString:photoURL] placeholderImage:[UIImage imageNamed:@"placeholder"]];
【讨论】: