Loading/Downloading image from URL on Swift

前端 未结 30 2565
感动是毒
感动是毒 2020-11-21 05:39

I\'d like to load an image from a URL in my application, so I first tried with Objective-C and it worked, however, with Swift, I\'ve a compilation error:

相关标签:
30条回答
  • 2020-11-21 06:04

    swift 3 with error handling

    let url = URL(string: arr[indexPath.row] as! String)
    if url != nil {
        DispatchQueue.global().async {
            let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
            DispatchQueue.main.async {
                if data != nil {
                    cell.imgView.image = UIImage(data:data!)
                }else{
                    cell.imgView.image = UIImage(named: "default.png")
                }
            }
        }
    }
    

    With Extension

    extension UIImageView {
    
        func setCustomImage(_ imgURLString: String?) {
            guard let imageURLString = imgURLString else {
                self.image = UIImage(named: "default.png")
                return
            }
            DispatchQueue.global().async { [weak self] in
                let data = try? Data(contentsOf: URL(string: imageURLString)!)
                DispatchQueue.main.async {
                    self?.image = data != nil ? UIImage(data: data!) : UIImage(named: "default.png")
                }
            }
        }
    }
    

    Extension Usage

    myImageView. setCustomImage("url")
    

    With Cache support

    let imageCache = NSCache<NSString, UIImage>()
    
    extension UIImageView {
    
        func loadImageUsingCacheWithURLString(_ 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: \(String(describing: error))")
                        DispatchQueue.main.async { [weak self] in
                            self?.image = placeHolder
                        }
                        return
                    }
                    DispatchQueue.main.async { [weak self] in
                        if let data = data {
                            if let downloadedImage = UIImage(data: data) {
                                imageCache.setObject(downloadedImage, forKey: NSString(string: URLString))
                                self?.image = downloadedImage
                            }
                        }
                    }
                }).resume()
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-21 06:04

    Swift 2 with error Handle and custom request header

    Simply add extension to UIImageView:

    extension UIImageView {
        public func imageFromUrl(urlString: String) {
            if let url = NSURL(string: urlString) {
                let request = NSMutableURLRequest(URL: url)
                request.setValue("<YOUR_HEADER_VALUE>", forHTTPHeaderField: "<YOUR_HEADER_KEY>")
                NSURLSession.sharedSession().dataTaskWithRequest(request) {
                    (data, response, error) in
                    guard let data = data where error == nil else{
                        NSLog("Image download error: \(error)")
                        return
                    }
    
                    if let httpResponse = response as? NSHTTPURLResponse{
                        if httpResponse.statusCode > 400 {
                            let errorMsg = NSString(data: data, encoding: NSUTF8StringEncoding)
                            NSLog("Image download error, statusCode: \(httpResponse.statusCode), error: \(errorMsg!)")
                            return
                        }
                    }
    
                dispatch_async(dispatch_get_main_queue(), {
                    NSLog("Image download success")
                    self.image = UIImage(data: data)
                })
                }.resume()
            }
        }
    }
    

    And then, use the new imageFromUrl(urlString: String) to download image

    Usage:

    imageView.imageFromUrl("https://i.imgur.com/ONaprQV.png")
    
    0 讨论(0)
  • 2020-11-21 06:05

    FYI : For swift-2.0 Xcode7.0 beta2

    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!)
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-21 06:07

    (Swift 4 update) To answer the original question directly, here's the swift equivalent of the posted Objective-C snippet.

    let url = URL(string: image.url)
    let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
    imageView.image = UIImage(data: data!)
    

    DISCLAIMER:

    It's important to note that the Data(contentsOf:) method will download the contents of the url synchronously in the same thread the code is being executed, so do not invoke this in the main thread of your application.

    An easy way to make the same code run asynchronously, not blocking the UI, is by using GCD:

    let url = URL(string: image.url)
    
    DispatchQueue.global().async {
        let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
        DispatchQueue.main.async {
            imageView.image = UIImage(data: data!)
        }
    }
    

    That said, in real life applications, if you want to have the best User Experience and avoid multiple downloads of the same image, you may want to also have them not only downloaded, but cached. There's already quite a few libraries that does that very seamless and they are all really easy to use. I personally recommend Kingfisher:

    import Kingfisher
    
    let url = URL(string: "url_of_your_image")
    // this downloads the image asynchronously if it's not cached yet
    imageView.kf.setImage(with: url) 
    

    And that's it

    0 讨论(0)
  • 2020-11-21 06:08

    Kingfisher is one of the best library for load image into URL.

    Github URL - https://github.com/onevcat/Kingfisher

    // If you want to use Activity Indicator.
    imageview_pic.kf.indicatorType = .activity
    imageview_pic.kf.setImage(with: URL(string: "Give your url string"))
    
    // If you want to use custom placeholder image.
    imageview_pic.kf.setImage(with: URL(string: "Give your url string"), placeholder: UIImage(named: "placeholder image name"), options: nil, progressBlock: nil, completionHandler: nil)
    
    0 讨论(0)
  • 2020-11-21 06:08

    Here is Working code for Loading / Downloading image from URL. NSCache automatically and Display Placeholder image before download and Load Actual image (Swift 4 | Swift 5 Code).

    func NKPlaceholderImage(image:UIImage?, imageView:UIImageView?,imgUrl:String,compate:@escaping (UIImage?) -> Void){
        
        if image != nil && imageView != nil {
            imageView!.image = image!
        }
        
        var urlcatch = imgUrl.replacingOccurrences(of: "/", with: "#")
        let documentpath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        urlcatch = documentpath + "/" + "\(urlcatch)"
        
        let image = UIImage(contentsOfFile:urlcatch)
        if image != nil && imageView != nil
        {
            imageView!.image = image!
            compate(image)
            
        }else{
            
            if let url = URL(string: imgUrl){
                
                DispatchQueue.global(qos: .background).async {
                    () -> Void in
                    let imgdata = NSData(contentsOf: url)
                    DispatchQueue.main.async {
                        () -> Void in
                        imgdata?.write(toFile: urlcatch, atomically: true)
                        let image = UIImage(contentsOfFile:urlcatch)
                        compate(image)
                        if image != nil  {
                            if imageView != nil  {
                                imageView!.image = image!
                            }
                        }
                    }
                }
            }
        }
    }
    

    Use Like this :

    // Here imgPicture = your imageView
    // UIImage(named: "placeholder") is Display image brfore download and load actual image. 
    
    NKPlaceholderImage(image: UIImage(named: "placeholder"), imageView: imgPicture, imgUrl: "Put Here your server image Url Sting") { (image) in }
    
    0 讨论(0)
提交回复
热议问题