如何使用Alamofire在swift中加载图像

时间:2015-02-20 19:21:01

标签: swift afnetworking alamofire

我有一个集合视图控制器,它通过URL加载图像Async。 (像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 async加载到urlImage方面表现非常出色,这就是我想做的事情。

AFNetworking更适合这项任务吗? (然后是Alamofire) 如果不是,我不知道如何将AFNetworking添加到我的swift项目中,除了添加#import“AFNetworking.h”,我需要添加哪些文件?

请说明哪种方法最好,我的需求是性能,指控,缓存。 视图集合控制器就像Instegram一样,正在加载图像,同时向下滚动。 我希望我能够清楚地知道我需要什么,  谢谢

10 个答案:

答案 0 :(得分:46)

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

  

我应该何时使用AFNetworking?

     
      
  • UIKit扩展,例如将图像异步加载到UIImageView
  •   

回答你的问题:

  

AFNetworking更适合这项任务吗?

是!

但如果仍想使用vanilla Alamofire项目,可以这样获取图片:

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

P.S。

但如果您只是想加载图片(当然是异步) - 您根本不需要使用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")

答案 1 :(得分:17)

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


用法示例:

myImageView.setImageWithUrl(imageUrl, placeHolderImage: somePlaceHolderImage)

答案 2 :(得分:14)

取自Alamofire / README.md

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

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

https://github.com/Alamofire/AlamofireImage

答案 3 :(得分:7)

如果您想使用AFNetworking的UImageView框架,则必须在桥头文件中执行#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.
        */
      }
    }
  } 

有关使用Alamofire的详细信息,请参阅this tutorial

答案 4 :(得分: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) }
    }
}

答案 5 :(得分:4)

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

首先,你必须使用Alamofire创建一个GET请求来下载图像,你必须使用AlamofireImage Library中的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

                        }
                    })

                }
        }

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

完整示例代码:

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
}

答案 6 :(得分:1)

您可以使用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
            }
        })
}

答案 7 :(得分:0)

我开发了一个小而简单的CocoaPods库,可与Alamofire和Images配合使用。

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

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

找到

它有很好的文档和示例,因此您可以在几分钟内享受它。

我自己在一些项目中工作,包括集合视图和滚动。

答案 8 :(得分:0)

在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)
    }
}

答案 9 :(得分:-1)

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

 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!)
        })
        
    }
}