Как снова исправить UIActivityIndicatorView из startAnimation в расширении UIImageView, используемом в TableView - PullRequest
0 голосов
/ 13 мая 2019

У меня есть расширение UIImageView с методом загрузки установленного изображения, расширение также содержит UIActivityIndicatorView, которое я устанавливаю как вид перед загрузкой изображения, как только изображение загружено, я удаляю или скрываю UIActivityIndicatorView из UIImageView

extension UIImageView {

    private static let imageProcessingQueue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".imageprocessing", attributes:  .concurrent)

    var activityIndicator: UIActivityIndicatorView! {
        get {
            return objc_getAssociatedObject(self, &activityIndicatorAssociationKey) as? UIActivityIndicatorView
        }
        set(newValue) {
            objc_setAssociatedObject(self, &activityIndicatorAssociationKey, newValue, .OBJC_ASSOCIATION_RETAIN)
        }
    }

    func showActivityIndicatory() {

        // activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView()
        activityIndicator = UIActivityIndicatorView(frame: CGRect.init(x: 0, y: 0, width: 50, height: 50))
        activityIndicator.center = self.center
        activityIndicator.hidesWhenStopped = true
        activityIndicator.style = UIActivityIndicatorView.Style.gray

        self.isUserInteractionEnabled = false

        UIImageView.imageProcessingQueue.async {
            DispatchQueue.main.async {
                self.activityIndicator.startAnimating()
                self.addSubview(self.activityIndicator)

             }
        }
    }

    func hideIndicator() {
        UIImageView.imageProcessingQueue.async {
            DispatchQueue.main.async {
                self.activityIndicator.stopAnimating()
                self.activityIndicator.removeFromSuperview()

            }
        }
    }

    func setImage(url : String)  {
        self.showActivityIndicatory()
        operatorManager.loadImage(url: url) { (image) in
            self.image = image
            self.hideIndicator()
        }
    }
}

И затем я могу использовать эту функцию расширения следующим образом:

guard let cell = tableView.dequeueReusableCell(withIdentifier:"Tableview", for: indexPath) as? TableViewCell else {
    fatalError()
}

let imagees = list[indexPath.row]

cell.labelView.text = imagees.urlString
cell.iconView.setImage(url: imagees.urlString)

Это Operation для загрузки изображения из кэша, если доступно или изсервер.

    class LoadImageOperation: ConcurrentOps<UIImage> {

private let session: URLSession
private let url: String
private var task: URLSessionTask?
private var defaultImage: UIImage?
// MARK: - Init

init(session: URLSession = URLSession.shared, url: String) {
    self.session = session
    self.url = url
    self.defaultImage = UIImage(named: "icons")
}


override func main() {

    guard let imageURL = URL(string: url) else {
        cancel()
        return
    }



    if let cachedImage = DataCache.shared.object(forKey: url) {

        DispatchQueue.main.async {
        self.complete(result: cachedImage as! UIImage)

        }
       cancel()
    }


    task = session.downloadTask(with: imageURL){ (url,response,error) in

        guard let url = url ,
            let data = try? Data(contentsOf: url),
            let image = UIImage(data: data) else {

                DispatchQueue.main.async {

                    if error != nil {
                        self.complete(result: self.defaultImage!)
                    } else {
                         self.complete(result: self.defaultImage!)
                    }
                }
                return
        }
        DispatchQueue.main.async {

            DataCache.shared.saveObject(object: image, forKey: self.url)
            self.complete(result: image)
        }

    }
    task?.resume()


}

}

Операция управляется здесь,

func loadImage(url: String, completionHandler: @escaping (_ result: UIImage) ->Void) {

    let operation = LoadImageOperation(url: url)

    operation.completionHandler = completionHandler
    operation.name = "loadImageOperation"
    queueManager.enqueue(operation)

}

Когда мой tableView впервые начинает загружаться, indicator показывает и отлично скрывается, но когда я прокручиваю tableview, он снова начинает анимировать indicator на UIImageView.Как мне предотвратить это?

Ответы [ 2 ]

0 голосов
/ 16 мая 2019

Мне было просто поверить, что решение пока не опробовано. Это не лучшее решение, но оно решило мою проблему.

    func setImage(url : String)  {



    if DataCache.shared.object(forKey: url) != nil {


              self.hideIndicator()



    }else{
        self.showActivityIndicatory()
    }


    operatorManager.loadImage(url: url) { (image) in
        self.image = image
        self.hideIndicator()
    }
}

Я проверил, кешируется ли изображение до того, как я запустил Operation, если он кешируется, я скрываю UIActivityIndicatorView, иначе я его показываю. почему я думаю, что это не 100%, операция также проверяет наличие кэшированных изображений, которые, я думаю, могут увеличить процессор.

0 голосов
/ 13 мая 2019

Причина, по которой отображается индикатор активности, заключается в том, что при прокрутке ячейки используются повторно (из соображений производительности) для отображения новых данных.Это означает, что каждый раз, когда вы прокручиваете в новую ячейку, она будет загружаться и вызывать cellForRow, вызывая функцию, которая также загружает индикатор активности.

Вы должны предоставить больше информации о том, как вы обрабатываетеUITableView, если вам нужен пошаговый ответ, но я думаю, что вы могли бы реализовать кэширование изображений, чтобы избежать загрузки изображения каждый раз, когда вы загружаете ячейку.Проверьте этот ответ для получения дополнительной информации.

...