UIActivityIndicator - начать анимацию с задержкой - PullRequest
0 голосов
/ 07 октября 2018

Я создаю приложение, которое загружает данные из Интернета.

Обычно загрузка данных занимает 0,5-1 секунды.

Я использую UIActivityIndicator, чтобы показать пользователючто данные загружаются.


Теперь проблема в том, что немного раздражает то, что даже если загрузка занимает всего 0,5-1 секунды, индикатор запускается немедленно.

Isесть способ запустить анимацию только с задержкой в ​​2 секунды: и если загрузка до этого завершена, то даже не запускайте ее.

В настоящее время я делаю это:

func loadUserDetails(){

    var shouldStartActivityIndicator : Bool = true
    DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
        if shouldStartActivityIndicator {
            self.tableViewActivityIndicator.startAnimating()
        }
    }

    DispatchQueue.global().async {

        if GlobalSemaphores.shared.userDetails_semaphore.wait(timeout: .now()) == .timedOut { return }

        DispatchQueue.main.async {

            UserDetailsFunctions.shared.loadUserDetails(uId: self.userId) { response, userDetails in
                DispatchQueue.main.async {

                    // DO SOMETHING WITH THE DATA
                    // REMOVED THE LINES

                    self.tableViewActivityIndicator.stopAnimating()
                    shouldStartActivityIndicator = false

                    GlobalSemaphores.shared.userDetails_semaphore.signal()
                }
            }
        }
    }
}

Но это уродливо, и мне приходится везде переписывать ..

Есть ли однострочное решение для этого?Расширение?

РЕДАКТИРОВАТЬ:

Например, такой класс, как этот?К сожалению, это не сработает ..

EXC_BAD_ACCESS

class CustomActivityIndicatorView : UIActivityIndicatorView {

    var shouldStartActivityIndicator : Bool = false
    override func startAnimating() {
        shouldStartActivityIndicator = true
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
            if self.shouldStartActivityIndicator {
                self.startAnimating()
            }
        }

    }
    override func stopAnimating() {
        shouldStartActivityIndicator = false
        self.stopAnimating()
    }
}

Ответы [ 2 ]

0 голосов
/ 07 октября 2018

Вы, конечно, можете использовать пользовательский подкласс UIActivityIndicatorView.Вместо использования asyncAfter, который нельзя отменить, я бы использовал Timer:

class DelayedActivityIndicatorView: UIActivityIndicatorView {

    var delay: TimeInterval = 2.0   
    private var delayTimer: Timer?

    override func startAnimating() {
        guard self.delayTimer == nil else {
            return // Return if there is already a timer running
        }

        self.delayTimer = Timer.scheduledTimer(withTimeInterval: delay, repeats: false, block: { (timer) in
            self.delayTimer = nil
            super.startAnimating()
        })

    }

    override func stopAnimating() {
        self.delayTimer?.invalidate()
        self.delayTimer = nil
        super.stopAnimating()
    }

}

В вашей попытке произошла критическая ошибка;ваша переопределенная функция называется self.startAnimating, что означает, что ваша функция вызывала себя с бесконечной рекурсией, пока не взорвала стек и не потерпела крах.Вам нужно super.startAnimating для вызова исходной функции, а не переопределения.

0 голосов
/ 07 октября 2018

О, так что я не могу переопределить функции startAnimating() stopAnimating(), но это делает собственный функционал ..

class CustomActivityIndicatorView : UIActivityIndicatorView {

    var shouldStartActivityIndicator : Bool = false
    func startAnimatingWithDelay () {
        shouldStartActivityIndicator = true
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            if self.shouldStartActivityIndicator {
                self.startAnimating()
            }
        }

    }
    func stopAnimatingWithDelay() {
        shouldStartActivityIndicator = false
        self.stopAnimating()

    }
}
...