create a loading image/ activity indicator, until the image is shown in the screen in swift

喜你入骨 提交于 2020-06-18 10:41:33

问题


i want to show an activity indicator in the screen while the image is being downloaded from a website url then show in the images.image this is my code below. everytime i download image it print the status right away and the activity indicator never appear. been searching through the web but i still didnt understand. please help

 let mygroup = DispatchGroup()
 var activityIndicator = UIActivityIndicatorView()

func downloadpic(sender:UIButton){
    let catPictureURL = URL(string: addr)!

    // Creating a session object with the default configuration.
    // You can read more about it here https://developer.apple.com/reference/foundation/urlsessionconfiguration
    let session = URLSession(configuration: .default)

    // Define a download task. The download task will download the contents of the URL as a Data object and then you can do what you wish with that data.

    let downloadPicTask = session.dataTask(with: catPictureURL) { (data, response, error) in
        // The download has finished.
        if let e = error {
            print("Error downloading cat picture: \(e)")
        } else {
            // No errors found.
            // It would be weird if we didn't have a response, so check for that too.
            if let res = response as? HTTPURLResponse {
                // put loading screen here
                self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .white)
                self.activityIndicator.frame = CGRect(x: 0, y: 0, width: 46, height: 46)
                self.activityIndicator.startAnimating()
                self.mygroup.enter()
                print("downloading image")
                print("Downloaded cat picture with response code \(res.statusCode)")
                if let imageData = data {
                    // Finally convert that Data into an image and do what you wish with it.
                     self.images.image = UIImage(data: imageData)
                        self.mygroup.leave()
                        print("image already downloaded")
                        self.activityIndicator.stopAnimating()
                        self.activityIndicator.hidesWhenStopped = true


                    // Do something with your image.
                } else {
                    print("Couldn't get image: Image is nil")
                }
            } else {
                print("Couldn't get response code for some reason")
            }
        }
    }

    downloadPicTask.resume()
}

回答1:


You got this problem, because:

  1. You didn't add the activityIndicator to any views
  2. You configured the activityIndicator in the completionHandler block

Let configure in the activityIndicator the viewDidLoad() method:

self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
self.activityIndicator.frame = CGRect(x: 0, y: 0, width: 46, height: 46)
self.activityIndicator.hidesWhenStopped = true

view.addSubview(self.activityIndicator)

And start to animate it before resuming the dataTask

self.activityIndicator.startAnimating()

Then, stop it in the completionHandler

self.activityIndicator.stopAnimating()

The final code:

let mygroup = DispatchGroup()
var activityIndicator = UIActivityIndicatorView()

override func viewDidLoad() {
    super.viewDidLoad()

    self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
    self.activityIndicator.frame = CGRect(x: 0, y: 0, width: 46, height: 46)
    self.activityIndicator.hidesWhenStopped = true

    view.addSubview(self.activityIndicator)
}

func downloadpic(sender: UIButton) {
    let catPictureURL = URL(string: addr)!

    // Creating a session object with the default configuration.
    // You can read more about it here https://developer.apple.com/reference/foundation/urlsessionconfiguration
    let session = URLSession(configuration: .default)

    // Define a download task. The download task will download the contents of the URL as a Data object and then you can do what you wish with that data.

    self.activityIndicator.startAnimating()

    let downloadPicTask = session.dataTask(with: catPictureURL) { (data, response, error) in
        // The download has finished.
        if let e = error {
            print("Error downloading cat picture: \(e)")
        } else {
            // No errors found.
            // It would be weird if we didn't have a response, so check for that too.
            if let res = response as? HTTPURLResponse {
                // put loading screen here

                self.mygroup.enter()
                print("downloading image")
                print("Downloaded cat picture with response code \(res.statusCode)")
                if let imageData = data {
                    // Finally convert that Data into an image and do what you wish with it.
                    self.images.image = UIImage(data: imageData)
                    self.mygroup.leave()
                    print("image already downloaded")
                    self.activityIndicator.stopAnimating()

                    // Do something with your image.
                } else {
                    print("Couldn't get image: Image is nil")
                }
            } else {
                print("Couldn't get response code for some reason")
            }
        }
    }

    downloadPicTask.resume()
}

The result!




回答2:


I recomend you to use library like AlamofireImage, and chose custom class in UIImageView.

Make the Custom Class of UIImageView:

import Foundation
import UIKit
import AlamofireImage

class CustomImageView: UIImageView {

    func ImageViewLoading(mediaUrl: String) {
        guard let url = URL(string: mediaUrl) else { return }
        let activityIndicator = self.activityIndicator
        DispatchQueue.main.async {
            activityIndicator.startAnimating()
        }
        self.af.setImage(
            withURL: url,
            placeholderImage: nil,
            filter: nil,
            completion: { response in
                DispatchQueue.main.async {
                    activityIndicator.stopAnimating()
                    activityIndicator.removeFromSuperview()
                }
            }
        )
    }

    private var activityIndicator: UIActivityIndicatorView {
        let activityIndicator = UIActivityIndicatorView()
        activityIndicator.hidesWhenStopped = true
        activityIndicator.color = UIColor.black
        self.addSubview(activityIndicator)

        activityIndicator.translatesAutoresizingMaskIntoConstraints = false

        let centerX = NSLayoutConstraint(item: self,
                                         attribute: .centerX,
                                         relatedBy: .equal,
                                         toItem: activityIndicator,
                                         attribute: .centerX,
                                         multiplier: 1,
                                         constant: 0)
        let centerY = NSLayoutConstraint(item: self,
                                         attribute: .centerY,
                                         relatedBy: .equal,
                                         toItem: activityIndicator,
                                         attribute: .centerY,
                                         multiplier: 1,
                                         constant: 0)
        self.addConstraints([centerX, centerY])
        return activityIndicator
    }

}

Use this class to your UIImageView:

@IBOutlet weak var photoImageViewWithLoading: CustomImageView!

photoImageViewWithLoading.ImageViewLoading(mediaUrl: mediaUrl!)

When you load image from url the UIImageView will show the activityindicator

I have this answer will help you.

Note: I use Swift 5



来源:https://stackoverflow.com/questions/43404129/create-a-loading-image-activity-indicator-until-the-image-is-shown-in-the-scre

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!