【问题标题】:How to load image in swift using Alamofire如何使用 Alamofire 快速加载图像
【发布时间】:2015-04-22 13:59:40
【问题描述】:

我有一个集合视图控制器,它通过 URL 加载图像异步。 (类似于 Instegram) 我正在寻找实现加载图像部分的最佳方法。 请告诉我你的看法

第一种方式 - 没有任何外部库:

   let downloadQueue = dispatch_queue_create("com.pro.asyncImages",nil)
    dispatch_async(downloadQueue){

        var data = NSData(contentsOfURL: NSURL(string: pictureUrl!)!)

        var image: UIImage?
        if (data != nil){
            image = UIImage(data: data!)
        }
        dispatch_async(dispatch_get_main_queue()){
            uiImageView.image = image
        }
    }

第二种方式——使用Alamofire(请求属于Alamofire)

if let  mediaUrl = info.mediaUrl {
        request(.GET,mediaUrl).response(){
            (_, _, data, _) in
            let image = UIImage(data: data! as NSData)
            imageView.image = image
        }
    }

最后,我读到 AFNetworking 在将 url 异步加载到 urlImage 方面做得很好,这就是我想要做的。

那么 AFNetworking 是否更适合这项任务? (然后是阿拉莫菲尔) 如果没有,我不明白如何将 AFNetworking 添加到我的 swift 项目中,除了添加 #import “AFNetworking.h” 之外,我还需要添加哪些文件?

请解释哪种方法最好,我的需求是性能,指责,缓存。 视图集合控制器的行为类似于 Instegram 并在向下滚动时加载图像。 我希望我足够清楚我需要什么, 谢谢

【问题讨论】:

  • AFNetworking 的编码器与 Alamofire 相同,我认为是相同的实现,但在 Swift 中

标签: swift afnetworking alamofire


【解决方案1】:

正如作者在 Alamofire README.md 中提到的那样:

什么时候应该使用 AFNetworking?

  • UIKit 扩展,比如异步加载图片到 UIImageView

所以回答你的问题:

那么 AFNetworking 是否更适合这项任务?

是的!

但如果还想用原版Alamofire项目,可以这样获取图片:

   Alamofire.request(.GET, "https://robohash.org/123.png").response { (request, response, data, error) in
        self.myImageView.image = UIImage(data: data, scale:1)
    }

附言

但是,如果您只想加载图像(当然是异步的)- 您根本不需要使用 AlamofireAFNetworking。 只需在您的代码中添加这个小扩展:

extension UIImageView {
    public func imageFromUrl(urlString: String) {
        if let url = NSURL(string: urlString) {
            let request = NSURLRequest(URL: url)
            NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {
                (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
                self.image = UIImage(data: data)
            }
        }
    }
}

并使用它:

myImageView.imageFromUrl("https://robohash.org/123.png")

【讨论】:

  • sendAsynchronousRequest 在 iOS 9 中已弃用。请改用 NSURLSession.dataTaskWithURL,尽管我总是会选择 Alamofire,尤其是 RxAlamofire,请参阅下面的答案。
  • 这似乎已从自述文件中删除-因此不再是当前信息
  • 我喜欢扩展解决方案。很干净。我会在扩展中添加一个占位符图像。
【解决方案2】:

我在这里创建了一个 Swift 版本的 UIImageView+AFNetworking:Github
您不必在项目中使用 AFNetworking(和桥接头)或 Alamofire。只需将文件添加到您的项目并使用它。


示例用法:

myImageView.setImageWithUrl(imageUrl, placeHolderImage: somePlaceHolderImage)

【讨论】:

  • 在找到你的文件之前,我需要为这个文件集成整个框架.....大谢谢
  • @MrugeshTank:哈哈,是的,这就是写这篇文章的重点:D
  • 如果我使用 Github 链接中提到的文件,如何设置/重置缓存?此缓存是否有最大大小?
  • 1) 不适用于 Swift 2 2) 这与 Alamofire 无关 3) 这不是问题的答案。
【解决方案3】:

取自 Alamofire/README.md

“为了让 Alamofire 专注于核心网络实施,Alamofire 软件基金会创建了额外的组件库,为 Alamofire 生态系统带来额外的功能。

AlamofireImage - 一个图像库,包括图像响应序列化程序、UIImage 和 UIImageView 扩展、自定义图像过滤器、自动清除内存缓存和基于优先级的图像下载系统。”

https://github.com/Alamofire/AlamofireImage

【讨论】:

  • 我是一个新手,遵循过时的教程 (raywenderlich.com/85080/beginning-alamofire-tutorial),我需要将其转换为最新的 swift 2.0+alamofire 3 设置。为此,我认为我还需要安装 AlomofireImage,但我该怎么做呢?和我安装 alamofire 的方法一样吗?
  • AlamofireImage 为我解决了缓存通过 http 获取的图像的问题
【解决方案4】:

在 swift 5 和 Alamofire 5 中,您可以像下面这样使用..

  AF.request( "https://robohash.org/123.png",method: .get).response{ response in

   switch response.result {
    case .success(let responseData):
        self.myImageView.image = UIImage(data: responseData!, scale:1)

    case .failure(let error):
        print("error--->",error)
    }
}

【讨论】:

    【解决方案5】:

    如果你想使用 AFNetworking 的 UImageView 框架,你必须在你的 bridge-header 文件中做#import "UIImageView+AFNetworking.h"

    AFNetworking 具有共享缓存,因此您无需手动缓存或取消您的请求。来自 AFNetworking 的 setImageWithURL 可以轻松地将 URL 转换为 ImageView 中的图像。

    使用UIImage+AFNetworking的示例代码:

    cell.imageView.setImageWithURL(NSURL(string:imageSource), placeholderImage: UIImage(named:"placeholder"))
    

    如果您使用的是 Alamofire,则必须手动将 NSData 转换为 UIImage。对于 Alamofire,您可以创建一个 NSCache() 对象来缓存您的图像。两个库的性能应该相似。您可以使用 Alamofire 进行服务器 API 调用,然后使用 AFNetworking 异步显示图像。

    使用 Alamofire 进行图像缓存的示例代码:

    let imageCache = NSCache()
    
     if let image = self.imageCache.objectForKey(imageURL) as? UIImage {
        cell.imageView.image = image
      } else {
        // 3
        cell.imageView.image = nil
    
        // 4
        cell.request = Alamofire.request(.GET, imageURL).validate(contentType: ["image/*"]).responseImage() {
          (request, _, image, error) in
          if error == nil && image != nil {
            // 5
            self.imageCache.setObject(image!, forKey: request.URLString)
    
            // 6
            if request.URLString == cell.request?.request.URLString {
              cell.imageView.image = image
            }
          } else {
            /*
            If the cell went off-screen before the image was downloaded, we cancel it and
            an NSURLErrorDomain (-999: cancelled) is returned. This is a normal behavior.
            */
          }
        }
      } 
    

    您可以阅读this tutorial 了解有关使用 Alamofire 的更多详细信息。

    【讨论】:

    • 这非常有帮助,我发现添加 AFNetworking 比在我的项目中添加代码更容易和快速,非常感谢!
    • 与使用 NSURLCache 控制图像缓存相比,这样做有什么优势吗?
    • 有一个单独的库 AlamofireImage 用于处理图像。它还负责缓存和更多选项 - github.com/Alamofire/AlamofireImage
    【解决方案6】:

    这是使用 RxAlamofire 的一种方法:

    import Alamofire
    import RxAlamofire
    
    extension UIImageView {
        public func imageFromUrl(urlString: String) {
            requestData(.GET, urlString)
                .observeOn(MainScheduler.instance)
                .subscribeNext { self.image = UIImage(data: $0.1) }
        }
    }
    

    【讨论】:

    • 我尝试了您的方法,但随后出现以下错误:使用未解析的标识符“MainScheduler”。任何线索如何摆脱它?
    • 没关系,解决了这个问题。必须安装 RxSwift 和 RxCocoa,因为 RxAlamofire 依赖于它们。很好的解决方案。谢谢!
    【解决方案7】:

    实际上有多种方法可以使用 Alamofire 从 URL 加载图像。 这是我开发的一种方式,我已经在我的一个 Swift 项目中使用它。这样我就可以异步加载图像并将它们显示到 UITableView 中,从性能方面来看它很好,并且在滚动 UITableView 时没有阻塞,因为它关心兑现加载的图像。

    首先你必须使用 Alamofire 创建一个 GET 请求来下载图像,你必须使用来自 AlamofireImage 库的 Request+AlamofireImage 所以你必须

    import AlamofireImage
    

    然后在

        override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    

    }

    你必须像这样调用你的图片下载请求:

             //Download image
            // We should perform this in a background thread
            Alamofire.request(.GET, deshItem.dish_imageUrl!)
                .responseImage { response in
                    debugPrint(response)
    
                    print(response.request)
                    print(response.response)
                    debugPrint(response.result)
    
                    if let image = response.result.value {
                        print("image downloaded: \(image)")
    
                        // Store the commit date in to our cache
                        self.ImageCache[dishName!] = image
    
                        // Update the cell
                        dispatch_async(dispatch_get_main_queue(), {
                            if let cellToUpdate = tableView.cellForRowAtIndexPath(indexPath) {
                                    let dishImageView:UIImageView = cellToUpdate.viewWithTag(104) as! UIImageView
                                    dishImageView.image = image
    
                            }
                        })
    
                    }
            }
    

    对于图像缓存,我创建了一个字典,其中包含每个单元格或项目(字符串)的图像,因此这种缓存图像的方式将避免滚动时出现的锁定。

    完整的示例代码:

    import AlamofireImage
    
    class MainFeedTableViewController: UITableViewController, FloatRatingViewDelegate {
    
    var ImageCache = [String:UIImage]()
    
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("MainFeedCellID", forIndexPath: indexPath)
    
        // Configure the cell...
    
        let dishName = deshItem.dish_name
    
        //This is a workaround to cash the image and improve the performance while user scrolling UITableView.
        // If this image is already cached, don't re-download
        if let dishImage = ImageCache[dishName!] {
                    let dishImageView:UIImageView = cell.viewWithTag(104) as! UIImageView
                    dishImageView.image = dishImage
        }
        else {
            //Download image
            // We should perform this in a background thread
            Alamofire.request(.GET, deshItem.dish_imageUrl!)
                .responseImage { response in
                    debugPrint(response)
    
                    print(response.request)
                    print(response.response)
                    debugPrint(response.result)
    
                    if let image = response.result.value {
                        print("image downloaded: \(image)")
    
                        // Store the commit date in to our cache
                        self.ImageCache[dishName!] = image
    
                        // Update the cell
                        dispatch_async(dispatch_get_main_queue(), {
                            if let cellToUpdate = tableView.cellForRowAtIndexPath(indexPath) {
                                    let dishImageView:UIImageView = cellToUpdate.viewWithTag(104) as! UIImageView
                                    dishImageView.image = image
    
                            }
                        })
    
                    }
            }
    
        }
    
    
    
        return cell
    }
    

    【讨论】:

      【解决方案8】:

      您可以使用responseData(queue:completionHandler:)下载图片

      SWIFT 4

      func downloadImages(imageURL: String) {
      
          Alamofire.request(imageURL, method: .get)
              .validate()
              .responseData(completionHandler: { (responseData) in
                  self.yourImageVIew.image = UIImage(data: responseData.data!) 
                  DispatchQueue.main.async {
                      // Refresh you views
                  }
              })
      }
      

      【讨论】:

        【解决方案9】:

        我开发了一个小而直接的 CocoaPods 库来处理 Alamofire 和 Images。

        CocoaPods 是解决库依赖需求的好方法。它易于安装一次,并且易于向您的项目添加和更新依赖项。

        该库是开源的,可以在https://github.com/gchiacchio/AlamoImage找到

        它包含带有示例的出色文档,因此您将在几分钟内享受它。

        我自己在几个项目中使用它,包括集合视图和滚动。

        【讨论】:

          【解决方案10】:

          建议使用 urlsession 作为 swift 5 中弃用的 urlconnection

           public func imageFromUrl(urlString: String){
              if let url = URL(string: urlString) {
                  let request = URLRequest(url: url)
                  let session = URLSession(configuration: .default)
                  session.dataTask(with: request,completionHandler: {(data,response,error) in
                      self.image = UIImage(data: data!)
                  })
                  
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2017-10-20
            • 2018-12-29
            • 2016-11-17
            • 1970-01-01
            • 1970-01-01
            • 2021-07-09
            • 1970-01-01
            • 2013-04-03
            • 2018-08-05
            相关资源
            最近更新 更多