Подтвердить что ты не робот

Загрузка "наложения" при выполнении длинных задач в iOS

Что такое пример загрузки наложения в приложении Swift IOS, когда выполняются длительные задачи. Пример загрузки данных с удаленного сервера. Я googled, но не нашел ответа.

Обновлено:

Спасибо за @Sebastian Dressler, это простой способ. Я обновил свой код, и он работает классно

public class LoadingOverlay{

var overlayView = UIView()
var activityIndicator = UIActivityIndicatorView()

class var shared: LoadingOverlay {
    struct Static {
        static let instance: LoadingOverlay = LoadingOverlay()
    }
    return Static.instance
}

    public func showOverlay(view: UIView) {

        overlayView.frame = CGRectMake(0, 0, 80, 80)
        overlayView.center = view.center
        overlayView.backgroundColor = UIColor(hex: 0x444444, alpha: 0.7)
        overlayView.clipsToBounds = true
        overlayView.layer.cornerRadius = 10

        activityIndicator.frame = CGRectMake(0, 0, 40, 40)
        activityIndicator.activityIndicatorViewStyle = .WhiteLarge
        activityIndicator.center = CGPointMake(overlayView.bounds.width / 2, overlayView.bounds.height / 2)

        overlayView.addSubview(activityIndicator)
        view.addSubview(overlayView)

        activityIndicator.startAnimating()
    }

    public func hideOverlayView() {
        activityIndicator.stopAnimating()
        overlayView.removeFromSuperview()
    }
}

используя:

LoadingOverlay.shared.showOverlay(self.view)
//To to long tasks
LoadingOverlay.shared.hideOverlayView()
4b9b3361

Ответ 1

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

let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .Alert)

alert.view.tintColor = UIColor.blackColor()
let loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRectMake(10, 5, 50, 50)) as UIActivityIndicatorView
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
loadingIndicator.startAnimating();

alert.view.addSubview(loadingIndicator)
presentViewController(alert, animated: true, completion: nil)

Swift 3.0

let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)

let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
loadingIndicator.startAnimating();

alert.view.addSubview(loadingIndicator)
present(alert, animated: true, completion: nil)

Swift 4.0 и новее

let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)

let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.style = UIActivityIndicatorView.Style.gray
loadingIndicator.startAnimating();

alert.view.addSubview(loadingIndicator)
present(alert, animated: true, completion: nil)

и вы можете скрыть это следующим образом:

dismiss(animated: false, completion: nil)

Это будет показано следующим образом: enter image description here

Ответ 2

Просто создайте оверлейное представление, которое вы добавите в родительское представление, и удалите его, как только ваша задача будет выполнена, например. для добавления:

var overlay : UIView? // This should be a class variable

[ ... ]

overlay = UIView(frame: view.frame)
overlay!.backgroundColor = UIColor.blackColor()
overlay!.alpha = 0.8

view.addSubview(overlay!)

Для удаления:

overlay?.removeFromSuperview()

Ответ 3

Размытие фона + индикатор активности, пример Swift 5

extension UIView {
    func showBlurLoader() {
        let blurLoader = BlurLoader(frame: frame)
        self.addSubview(blurLoader)
    }

    func removeBluerLoader() {
        if let blurLoader = subviews.first(where: { $0 is BlurLoader }) {
            blurLoader.removeFromSuperview()
        }
    }
}


class BlurLoader: UIView {

    var blurEffectView: UIVisualEffectView?

    override init(frame: CGRect) {
        let blurEffect = UIBlurEffect(style: .dark)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.frame = frame
        blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        self.blurEffectView = blurEffectView
        super.init(frame: frame)
        addSubview(blurEffectView)
        addLoader()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func addLoader() {
        guard let blurEffectView = blurEffectView else { return }
        let activityIndicator = UIActivityIndicatorView(style: .whiteLarge)
        activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
        blurEffectView.contentView.addSubview(activityIndicator)
        activityIndicator.center = blurEffectView.contentView.center
        activityIndicator.startAnimating()
    }
}

demo

Ответ 4

Для тех, кто опаздывает, как и я, я внесла некоторые изменения в код @Sonrobby. Как я понимаю, @Sonrobby добавляет активность к наложению при каждом вызове showOverlay. И часть конфигурации может быть передана функции init, позволяя только размещение по методу showOverlay.

Я также меняю оверлейный фон на черный, так как мое приложение в основном белое.

вот код:

public class LoadingOverlay{

    var overlayView : UIView!
    var activityIndicator : UIActivityIndicatorView!

    class var shared: LoadingOverlay {
        struct Static {
            static let instance: LoadingOverlay = LoadingOverlay()
        }
        return Static.instance
    }

    init(){
        self.overlayView = UIView()
        self.activityIndicator = UIActivityIndicatorView()

        overlayView.frame = CGRectMake(0, 0, 80, 80)
        overlayView.backgroundColor = UIColor(white: 0, alpha: 0.7)
        overlayView.clipsToBounds = true
        overlayView.layer.cornerRadius = 10
        overlayView.layer.zPosition = 1

        activityIndicator.frame = CGRectMake(0, 0, 40, 40)
        activityIndicator.center = CGPointMake(overlayView.bounds.width / 2, overlayView.bounds.height / 2)
        activityIndicator.activityIndicatorViewStyle = .WhiteLarge
        overlayView.addSubview(activityIndicator)
    }

    public func showOverlay(view: UIView) {
        overlayView.center = view.center
        view.addSubview(overlayView)
        activityIndicator.startAnimating()
    }

    public func hideOverlayView() {
        activityIndicator.stopAnimating()
        overlayView.removeFromSuperview()
    }
}

Ответ 5

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

Если вы столкнулись с проблемой, подобной моей, есть одно исправление для кода и изменение подхода, который я рекомендую.

ИСПРАВЛЕНИЕ: Поместите оба блока кода в качестве замыканий на вызов dispatch_async, например:

dispatch_async(dispatch_get_main_queue(),
 { //code });

ПОДХОД. При вызове кода выполните dispatch_after вызов в основной очереди, чтобы задержать вызов на несколько миллисекунд.

Обоснование? Вы просто просите пользовательский интерфейс делать слишком много во время viewDidLoad.

Если бы это приложение к решению помогло, я был бы рад.

-Joel Long

P.S. Решение работало для XCode v6.3.2

Ответ 6

Обновлен ответ @sonrobby, добавлен фоновый просмотр и обработка ориентации с помощью маски изменения размера... это можно использовать для простых вещей

public class LoadingOverlay{

    var overlayView = UIView()
    var activityIndicator = UIActivityIndicatorView()
    var bgView = UIView()

    class var shared: LoadingOverlay {
        struct Static {
            static let instance: LoadingOverlay = LoadingOverlay()
        }
        return Static.instance
    }

    public func showOverlay(view: UIView) {

        bgView.frame = view.frame
        bgView.backgroundColor = UIColor.gray
        bgView.addSubview(overlayView)
        bgView.autoresizingMask = [.flexibleLeftMargin,.flexibleTopMargin,.flexibleRightMargin,.flexibleBottomMargin,.flexibleHeight, .flexibleWidth]
        overlayView.frame = CGRect(x: 0, y: 0, width: 80, height: 80)
        overlayView.center = view.center
        overlayView.autoresizingMask = [.flexibleLeftMargin,.flexibleTopMargin,.flexibleRightMargin,.flexibleBottomMargin]
        overlayView.backgroundColor = UIColor.black
        overlayView.clipsToBounds = true
        overlayView.layer.cornerRadius = 10

        activityIndicator.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
        activityIndicator.activityIndicatorViewStyle = .whiteLarge
        activityIndicator.center = CGPoint(x: overlayView.bounds.width / 2, y: overlayView.bounds.height / 2)

        overlayView.addSubview(activityIndicator)
        view.addSubview(bgView)
        self.activityIndicator.startAnimating()

    }

    public func hideOverlayView() {
        activityIndicator.stopAnimating()
        bgView.removeFromSuperview()
    }
}

если вы добавите его в keywindow, он может затем перейти к вашим навигационным и табуляторам... что-то вроде этого

LoadingOverlay.shared.showOverlay(view: UIApplication.shared.keyWindow!)

Ответ 8

Swift 3.

Я использовал код @Lucho в своем ответе ниже, и я изменил цвет фона наложения, чтобы очистить и добавил цвет прядильщика.

public class LoadingOverlay {

    var overlayView : UIView!
    var activityIndicator : UIActivityIndicatorView!

    class var shared: LoadingOverlay {
        struct Static {
            static let instance: LoadingOverlay = LoadingOverlay()
        }
        return Static.instance
    }

    init(){
        self.overlayView = UIView()
        self.activityIndicator = UIActivityIndicatorView()

        overlayView.frame = CGRect(0, 0, 80, 80)
        overlayView.backgroundColor = .clear
        overlayView.clipsToBounds = true
        overlayView.layer.cornerRadius = 10
        overlayView.layer.zPosition = 1

        activityIndicator.frame = CGRect(0, 0, 40, 40)
        activityIndicator.center = CGPoint(overlayView.bounds.width / 2, overlayView.bounds.height / 2)
        activityIndicator.activityIndicatorViewStyle = .whiteLarge
        activityIndicator.color = .gray
        overlayView.addSubview(activityIndicator)
    }

    public func showOverlay(view: UIView) {
        overlayView.center = view.center
        view.addSubview(overlayView)
        activityIndicator.startAnimating()
    }

    public func hideOverlayView() {
        activityIndicator.stopAnimating()
        overlayView.removeFromSuperview()
    }
}

Ответ 9

Я создал протокол для представления вашего собственного контроллера вида в виде наложения. Использование очень просто:

class ViewController: UIViewController, OverlayHost {
    @IBAction func showOverlayButtonPressed() {
        showOverlay(type: YourOverlayViewController.self, 
            fromStoryboardWithName: "Main")
    }
}

Результат:

Swift OverlayViewController

Исходный код: https://github.com/agordeev/OverlayViewController

Связанная статья: https://andreygordeev.com/2017/04/18/overlay-view-controller-protocols-swift/