Loading/Downloading image from URL on Swift

前端 未结 30 2522
感动是毒
感动是毒 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 05:57

    The only things there is missing is a !

    let url = NSURL.URLWithString("http://live-wallpaper.net/iphone/img/app/i/p/iphone-4s-wallpapers-mobile-backgrounds-dark_2466f886de3472ef1fa968033f1da3e1_raw_1087fae1932cec8837695934b7eb1250_raw.jpg");
    var err: NSError?
    var imageData :NSData = NSData.dataWithContentsOfURL(url!,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err)
    var bgImage = UIImage(data:imageData!)
    
    0 讨论(0)
  • Swift 4.1 I have crated a function just pass image url, cache key after image is generated set it to completion block.

       class NetworkManager: NSObject {
    
      private var imageQueue = OperationQueue()
      private var imageCache = NSCache<AnyObject, AnyObject>()
    
      func downloadImageWithUrl(imageUrl: String, cacheKey: String, completionBlock: @escaping (_ image: UIImage?)-> Void) {
    
        let downloadedImage = imageCache.object(forKey: cacheKey as AnyObject)
        if let  _ = downloadedImage as? UIImage {
          completionBlock(downloadedImage as? UIImage)
        } else {
          let blockOperation = BlockOperation()
          blockOperation.addExecutionBlock({
            let url = URL(string: imageUrl)
            do {
              let data = try Data(contentsOf: url!)
              let newImage = UIImage(data: data)
              if newImage != nil {
                self.imageCache.setObject(newImage!, forKey: cacheKey as AnyObject)
                self.runOnMainThread {
                  completionBlock(newImage)
                }
              } else {
                completionBlock(nil)
              }
            } catch {
              completionBlock(nil)
            }
          })
          self.imageQueue.addOperation(blockOperation)
          blockOperation.completionBlock = {
            print("Image downloaded \(cacheKey)")
          }
        }
      }
    }
    extension NetworkManager {
      fileprivate func runOnMainThread(block:@escaping ()->Void) {
        if Thread.isMainThread {
          block()
        } else {
          let mainQueue = OperationQueue.main
          mainQueue.addOperation({
            block()
          })
        }
      }
    }
    
    0 讨论(0)
  • 2020-11-21 06:01
    class ImageStore: NSObject { 
        static let imageCache = NSCache<NSString, UIImage>()
    }
    
    extension UIImageView {
        func url(_ url: String?) {
            DispatchQueue.global().async { [weak self] in
                guard let stringURL = url, let url = URL(string: stringURL) else {
                    return
                }
                func setImage(image:UIImage?) {
                    DispatchQueue.main.async {
                        self?.image = image
                    }
                }
                let urlToString = url.absoluteString as NSString
                if let cachedImage = ImageStore.imageCache.object(forKey: urlToString) {
                    setImage(image: cachedImage)
                } else if let data = try? Data(contentsOf: url), let image = UIImage(data: data) {
                    DispatchQueue.main.async {
                        ImageStore.imageCache.setObject(image, forKey: urlToString)
                        setImage(image: image)
                    }
                }else {
                    setImage(image: nil)
                }
            }
        }
    }
    

    Usage :

    let imageView = UIImageView()
    imageView.url("image url")
    
    0 讨论(0)
  • 2020-11-21 06:02

    Swift 4::

    This will shows loader while loading the image. You can use NSCache which store image temporarily

    let imageCache = NSCache<NSString, UIImage>()
    extension UIImageView {
        func loadImageUsingCache(withUrl urlString : String) {
            let url = URL(string: urlString)
            if url == nil {return}
            self.image = nil
    
            // check cached image
            if let cachedImage = imageCache.object(forKey: urlString as NSString)  {
                self.image = cachedImage
                return
            }
    
            let activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView.init(activityIndicatorStyle: .gray)
            addSubview(activityIndicator)
            activityIndicator.startAnimating()
            activityIndicator.center = self.center
    
            // 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
                        activityIndicator.removeFromSuperview()
                    }
                }
    
            }).resume()
        }
    }
    

    Usage:-

    truckImageView.loadImageUsingCache(withUrl: currentTruck.logoString)
    
    0 讨论(0)
  • 2020-11-21 06:03

    You’ll want to do:

    UIImage(data: data)
    

    In Swift, they’ve replaced most Objective C factory methods with regular constructors.

    See:

    https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-XID_26

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

    If you just want to load image (Asynchronously!) - just add this small extension to your swift code:

    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
                    if let imageData = data as NSData? {
                        self.image = UIImage(data: imageData)
                    }
                }
            }
        }
    }
    

    And use it this way:

    myImageView.imageFromUrl("https://robohash.org/123.png")
    
    0 讨论(0)
提交回复
热议问题