创建加载图像/活动指示器,直到图像以swift显示在屏幕上

创建加载图像/活动指示器,直到图像以swift显示在屏幕上,swift,loading,Swift,Loading,我想在从网站url下载图像时在屏幕上显示活动指示器,然后在图像中显示。图像这是我下面的代码。每次我下载图像时,它会立即打印状态,而活动指示器永远不会出现。我一直在网上搜索,但我还是不明白。请帮忙 let mygroup = DispatchGroup() var activityIndicator = UIActivityIndicatorView() func downloadpic(sender:UIButton){ let catPictureURL = URL(string

我想在从网站url下载图像时在屏幕上显示活动指示器,然后在图像中显示。图像这是我下面的代码。每次我下载图像时,它会立即打印状态,而活动指示器永远不会出现。我一直在网上搜索,但我还是不明白。请帮忙

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

您遇到了这个问题,因为:

  • 您没有将
    活动指示器添加到任何视图中
  • 您在
    completionHandler
    块中配置了
    activityIndicator
  • 让我们在
    activityIndicator
    中配置
    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)
    
    并在恢复
    dataTask

    self.activityIndicator.startAnimating()
    
    然后,在
    completionHandler

    self.activityIndicator.stopAnimating()
    
    最终代码:

    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()
    }
    
    结果


    您遇到了这个问题,因为:

  • 您没有将
    活动指示器添加到任何视图中
  • 您在
    completionHandler
    块中配置了
    activityIndicator
  • 让我们在
    activityIndicator
    中配置
    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)
    
    并在恢复
    dataTask

    self.activityIndicator.startAnimating()
    
    然后,在
    completionHandler

    self.activityIndicator.stopAnimating()
    
    最终代码:

    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()
    }
    
    结果


    我建议您使用类似AlamofireImage的库,并在UIImageView中选择自定义类

    创建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
        }
    
    }
    
    @IBOutlet weak var photoImageViewWithLoading: CustomImageView!
    
    photoImageViewWithLoading.ImageViewLoading(mediaUrl: mediaUrl!)
    
    将此类用于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
        }
    
    }
    
    @IBOutlet weak var photoImageViewWithLoading: CustomImageView!
    
    photoImageViewWithLoading.ImageViewLoading(mediaUrl: mediaUrl!)
    
    从url加载图像时,UIImageView将显示activityindicator

    我有这个答案会帮助你的


    注意:我使用Swift 5

    我建议您使用类似AlamofireImage的库,并在UIImageView中选择自定义类

    创建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
        }
    
    }
    
    @IBOutlet weak var photoImageViewWithLoading: CustomImageView!
    
    photoImageViewWithLoading.ImageViewLoading(mediaUrl: mediaUrl!)
    
    将此类用于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
        }
    
    }
    
    @IBOutlet weak var photoImageViewWithLoading: CustomImageView!
    
    photoImageViewWithLoading.ImageViewLoading(mediaUrl: mediaUrl!)
    
    从url加载图像时,UIImageView将显示activityindicator

    我有这个答案会帮助你的


    注意:我使用Swift 5

    我编写了一个使用SDWebImage的扩展。下面是我的代码,给出了一个很好的用户体验

    import SDWebImage
    
    extension UIImageView {    
        func imageURL(_ url: String) {
            let activityIndicator = UIActivityIndicatorView(style: .gray)
            activityIndicator.frame = CGRect(x: 0, y: 0, width: 64, height: 64)
            activityIndicator.hidesWhenStopped = true
            activityIndicator.startAnimating()
            activityIndicator.translatesAutoresizingMaskIntoConstraints = false
            
            activityIndicator.center = CGPoint(x: self.frame.size.width  / 2, y: self.frame.size.height / 2)
            
            self.addSubview(activityIndicator)
            
            //self.sd_setImage(with: URL(string: url), placeholderImage: UIImage(named: "placeholder.png"))
            self.sd_setImage(with: URL(string: url)) { (image, error, cacheType, url) in
                activityIndicator.stopAnimating()
            }
        }
    }
    

    我编写了一个使用SDWebImage的扩展。下面是我的代码,给出了一个很好的用户体验

    import SDWebImage
    
    extension UIImageView {    
        func imageURL(_ url: String) {
            let activityIndicator = UIActivityIndicatorView(style: .gray)
            activityIndicator.frame = CGRect(x: 0, y: 0, width: 64, height: 64)
            activityIndicator.hidesWhenStopped = true
            activityIndicator.startAnimating()
            activityIndicator.translatesAutoresizingMaskIntoConstraints = false
            
            activityIndicator.center = CGPoint(x: self.frame.size.width  / 2, y: self.frame.size.height / 2)
            
            self.addSubview(activityIndicator)
            
            //self.sd_setImage(with: URL(string: url), placeholderImage: UIImage(named: "placeholder.png"))
            self.sd_setImage(with: URL(string: url)) { (image, error, cacheType, url) in
                activityIndicator.stopAnimating()
            }
        }
    }
    

    我已经看到了活动指示器,但我没有将其包含在上面,因为问题是活动指示器启动后立即停止。我试图做的是在图像仍在下载时显示活动指示器。我需要使活动指示器在应用程序下载图像时启动,然后在图像显示在图像中后停止。图像查看我的附件!我想这就是你想要的。你是对的,对不起我的错误。谢谢你的回答。我已经看到了活动指示器。我没有把它包括在上面,因为问题是活动指示器启动后立即停止。我试图做的是在图像仍在下载时显示活动指示器。我需要使活动指示器在应用程序下载图像时启动,然后在图像显示在图像中后停止。图像查看我的附件!我想这就是你想要的。你是对的,对不起我的错误。谢谢您的回答。这是在UICollectionView中设置单元格活动指示器的便捷方法,但设置单元格中心的指示器需要设置。将AutoResizezingMaskintoConstraints=true。若要将指示器设置为中心,请将类似的内容替换为activityIndicator.center=CGPoint(x:self.frame.size.width/2,y:self.frame.size.height/2)到activityIndicator.center=self.center这是在UICollectionView中设置活动指示器到单元格的便捷方法,但为了将指示器设置到单元的中心,需要设置指示器。TranslatesAutoResizezingMaskintoConstraints=true。若要将指示器设置为中心,请使用activityIndicator.center=CGPoint(x:self.frame.size.width/2,y:self.frame.size.height/2)将此类似项替换为activityIndicator.center=self.center