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

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

【问题讨论】:

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

标签: ios uiimageview uiimage nsurl


【解决方案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
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2014-05-06
                • 2016-03-04
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-01-10
                • 2015-08-14
                • 2017-09-02
                相关资源
                最近更新 更多