Swift异步加载图像

Jan*_*han 29 asynchronous swift

我正在处理来自url异步的show image.我试图为下载图像创建一个新线程,然后刷新main thread.

func asyncLoadImg(product:Product,imageView:UIImageView){
    let downloadQueue = dispatch_queue_create("com.myApp.processdownload", nil)
    dispatch_async(downloadQueue){
        let data = NSData(contentsOfURL: NSURL(string: product.productImage)!)
        var image:UIImage?
        if data != nil{
            image = UIImage(data: data!)
        }
        dispatch_async(dispatch_get_main_queue()){
            imageView.image = image
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

当我尝试调试时,当涉及到dispatch_async(downloadQueue)时,它会跳出func.有什么建议吗?谢谢

Sho*_*ari 92

Swift 3.0+更新代码:(从jamesrochabrun获取帮助链接https://github.com/jamesrochabrun/JSONTutorialFinal )

let imageCache = NSCache<NSString, UIImage>()

extension UIImageView {

    func imageFromServerURL(_ URLString: String, placeHolder: UIImage?) {

        self.image = nil
        if let cachedImage = imageCache.object(forKey: NSString(string: URLString)) {
            self.image = cachedImage
            return
        }

        if let url = URL(string: URLString) {
            URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in

                //print("RESPONSE FROM API: \(response)")
                if error != nil {
                    print("ERROR LOADING IMAGES FROM URL: \(error)")
                    DispatchQueue.main.async {
                        self.image = placeHolder
                    }
                    return
                }
                DispatchQueue.main.async {
                    if let data = data {
                        if let downloadedImage = UIImage(data: data) {
                            imageCache.setObject(downloadedImage, forKey: NSString(string: URLString))
                            self.image = downloadedImage
                        }
                    }
                }
            }).resume()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Swift 3更新代码:

extension UIImageView {
    public func imageFromServerURL(urlString: String) {
        self.image = nil
        URLSession.shared.dataTask(with: NSURL(string: urlString)! as URL, completionHandler: { (data, response, error) -> Void in

            if error != nil {
                print(error)
                return
            }
            DispatchQueue.main.async(execute: { () -> Void in
                let image = UIImage(data: data!)
                self.image = image
            })

        }).resume()
    }}
Run Code Online (Sandbox Code Playgroud)

Swift 2.2代码:

 extension UIImageView {
        public func imageFromServerURL(urlString: String) {
    self.image = nil
            NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: { (data, response, error) -> Void in

                if error != nil {
                    print(error)
                    return
                }
                dispatch_async(dispatch_get_main_queue(), { () -> Void in
                    let image = UIImage(data: data!)
                    self.image = image
                })

            }).resume()
        }}
Run Code Online (Sandbox Code Playgroud)

现在,无论您需要什么,只需执行此操作即可从服务器URL加载图像:

  1. 使用占位符图像使用swift 3.0 +更新的代码:UIImageView.imageFromServerURL(URLString:"here server url",placeHolder:uiimage格式的占位符图像)

  2. Swfit 3或更少:UIImageView.imageFromServerURL("here server url")

简单!

  • 我认为这应该是正确的答案,因为它更简洁.:+1: (2认同)
  • @Kirill在Swift 3中更新了Code.试试吧 .希望它有助于解决您的问题 (2认同)
  • 你摇滚男人!解决了我滞后的UICollectionView! (2认同)

jav*_*muu 25

使用extensionSwift3.要解决网络问题,我建议您使用NSCache:

import UIKit

let imageCache = NSCache<NSString, AnyObject>()

extension UIImageView {
    func loadImageUsingCache(withUrl urlString : String) {
        let url = URL(string: urlString)
        self.image = nil

        // check cached image
        if let cachedImage = imageCache.object(forKey: urlString as NSString) as? UIImage {
            self.image = cachedImage
            return
        }

        // if not, download image from url
        URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
            if error != nil {
                print(error!)
                return
            }

            DispatchQueue.main.async {
                if let image = UIImage(data: data!) {
                    imageCache.setObject(image, forKey: urlString as NSString)
                    self.image = image
                }
            }

        }).resume()
    }
}
Run Code Online (Sandbox Code Playgroud)

希望它有所帮助!


spo*_*b92 5

继续 Shobhakar Tiwari 的回答,我认为在这些情况下,在出现错误的情况下使用默认图像以及出于加载目的通常很有帮助,因此我已将其更新为包含可选的默认图像:

斯威夫特 3

extension UIImageView {
public func imageFromServerURL(urlString: String, defaultImage : String?) {
    if let di = defaultImage {
        self.image = UIImage(named: di)
    }

    URLSession.shared.dataTask(with: NSURL(string: urlString)! as URL, completionHandler: { (data, response, error) -> Void in

        if error != nil {
            print(error ?? "error")
            return
        }
        DispatchQueue.main.async(execute: { () -> Void in
            let image = UIImage(data: data!)
            self.image = image
        })

    }).resume()
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 不要重复回答,您可以对答案发表评论,以便开发人员从中受益 (2认同)