iOS:从 url 加载图像

Posted

技术标签:

【中文标题】iOS:从 url 加载图像【英文标题】:iOS: load an image from url 【发布时间】:2012-06-13 21:53:58 【问题描述】:

我需要从 url 加载图像并将其设置在 UIImageView 中;问题是我不知道图片的确切尺寸,那我该如何正确显示图片呢?

【问题讨论】:

为什么会有问题?下载图像后,您将知道其大小。您还可以将图像视图设置为您想要的大小并拉伸图像以适合。 【参考方案1】:

只需使用 UIImage 的 size 属性即可,例如:

NSURL *url = [NSURL URLWithString:path];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[UIImage alloc] initWithData:data];
CGSize size = img.size;

【讨论】:

或者在图像视图上设置您想要的大小,然后在下载后拉伸图像以适合图像视图。 (你应该伸展并保持纵横比,其他一切看起来都很奇怪) 啊好的...但我不明白如何为我的 imageView 调整此图像的大小;我应该创建一个缩影,我的 imageView 没有太多空间(最大 236 宽度和最大 60 高度);在这个空间中,我应该从 url 加载图像,但它应该是成比例的...... 我想你想要的是将 UIImageView 的 contentMode 设置为 UIContentViewScaleAspectFit。但是请查看文档。 感谢此代码。我有一个问题,如何在检索图片时显示“正在加载”并在图片下载失败时通知? @Shannon 你得到答案了吗?【参考方案2】:

迅速:

var url = NSURL.URLWithString("http://www.example.com/picture.png")
var data = NSData(contentsOfURL : url)
var image = UIImage(data : data)
image.size // if you need it

【讨论】:

【参考方案3】:

关于使用选项的快速说明:

var url:NSURL? = NSURL(string: imageString)
var data:NSData? = NSData(contentsOfURL : url!)
var image = UIImage(data : data!)

【讨论】:

如果图像文件不在指定的图像字符串中,这将崩溃。 利用 if let 语句!这是不安全的代码,如果 url 为 nil 会崩溃【参考方案4】:

在 SWIFT 3.0 中

主线程必须始终保持空闲,以便为用户界面和用户交互提供服务。

class ViewController: UIViewController 

@IBOutlet weak var imageView: UIImageView!

private func fetchImage() 
    let imageURL = URL(string: "https://i.stack.imgur.com/9z6nS.png")
    var image: UIImage?
    if let url = imageURL 
        //All network operations has to run on different thread(not on main thread).
        DispatchQueue.global(qos: .userInitiated).async 
            let imageData = NSData(contentsOf: url)
            //All UI operations has to run on main thread.
            DispatchQueue.main.async 
                if imageData != nil 
                    image = UIImage(data: imageData as! Data)
                    self.imageView.image = image
                    self.imageView.sizeToFit()
                 else 
                    image = nil
                
            
        
    


override func viewDidLoad() 
    super.viewDidLoad()
    fetchImage()



【讨论】:

【参考方案5】:

要下载Kingfisher库的异步图像,你可以按照这个步骤,url:https://github.com/onevcat/Kingfisher:

 func imageFromUrl(_ urlString: String) 
        if let url = URL(string: urlString) 
            ImageDownloader.default.downloadImage(with: url, options: [], progressBlock: nil) 
                (image, error, url, data) in
                DispatchQueue.main.async 
                    self.imageView.image = image
                
            
        
    

您也可以使用默认 URLSession.shared.dataTask 下载图片

 func imageFromUrl(_ urlString: String) 
        if let url = URL(string: urlString) 
            let request = URLRequest(url: url)
            URLSession.shared.dataTask(with: request) (data,response,error) in
                if let imageData = data as Data? 
                    if let img = UIImage(data: imageData)
                       DispatchQueue.main.async 
                       self.imageView.image = img
                       
                    
                
            
        
    

【讨论】:

【参考方案6】:

SWIFT 5.0 + 后台获取

private func fetchImage(_ photoURL: URL?) 

    guard let imageURL = photoURL else  return  

    DispatchQueue.global(qos: .userInitiated).async 
        do
            let imageData: Data = try Data(contentsOf: imageURL)

            DispatchQueue.main.async 
                let image = UIImage(data: imageData)
                self.userImageView.image = image
                self.userImageView.sizeToFit()
                self.tableView.reloadData()
            
        catch
            print("Unable to load data: \(error)")
        
    

【讨论】:

【参考方案7】:

显示从 json 或 url 下载的图像的一个常见错误是队列问题。所有与 UI 相关的事情都需要在 主队列 中完成,因此如果您忘记了这一点,即使是完美的代码(以上答案都很好)有时也不会显示您的图像。要调用 mainQueue,使用这样的代码,并注意调用 main queue 可能需要在被调用的 imageDisplay 函数中单独完成:

dispatch_async(dispatch_get_main_queue(), ^

    self.nameLabel.text = self.pokemon.name;

    [self displayImage];  //CALLS FUNCTION
    self.abilitiesTextView.text = @"loves SwiftUI";
);

- (void)displayImage             

    NSString *imageURLString = [NSString stringWithFormat: self.pokemon.sprite];
    NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imageURLString]];
    dispatch_async(dispatch_get_main_queue(), ^
        self.spriteImageView.image = [UIImage  imageWithData: imageData];
    );

    // NOTE: important for newer versions of XCode/Obj-C...
    //[imageData release];   With ARC ("automated release..."), release method is forbidden, it's already done for you.

【讨论】:

【参考方案8】:

如果您愿意,甚至可以将其移至 UIImage 扩展名:

extension UIImage 
    
    //NOTE: This is not thread safe, please run it on a background thread.
    convenience init?(fromFile filePath:String) 
        guard let url = URL(string: filePath) else 
            return nil
        
        
        self.init(fromURL: url)
    
    
    //NOTE: This is not thread safe, please run it on a background thread.
    convenience init?(fromURL url:URL) 
        let imageData: Data
        
        do 
            imageData = try Data(contentsOf: url)
         catch 
            return nil
        
        
        self.init(data: imageData)
    
    

【讨论】:

【参考方案9】:

Swift 安全代码版本:

private func loadImage(from url:URL) -> UIImage? 
    let imageData: Data
    
    do 
        imageData = try Data(contentsOf: url)
     catch 
        return nil
    
    
    return UIImage(data: imageData)


private func loadImage(from urlString:String) -> UIImage? 
    guard let url = URL(string: urlString) else 
        return nil
    
    
    return self.loadImage(from: url)

请记住,此代码会阻塞主线程,因此您应该在后台线程上运行它。例如:

DispatchQueue.global().async 
    let image = UIImage(fromFile: "http://xpto.com/image.png")
    
    // And then you should update UI on main thread.
    // If you have an UIImageView outlet you can update its image this way:
    DispatchQueue.main.async 
        imageView.image = image
        imageView.contentMode = .scaleAspectFit
    

【讨论】:

以上是关于iOS:从 url 加载图像的主要内容,如果未能解决你的问题,请参考以下文章

在幻灯片 iOS APP 中从 URL Xcode 9 加载图像

如何从从json获得的url加载图像到collectionview

如何从 macOS Swift 上的文档目录加载图像?

无法从 URL 加载图像

Ionic app / ios & android 不使用动态 url 加载图像

ios以离线模式存储URL图像(未连接到互联网)