Swift:在自定义类中启动和停止活动指示器的动画

时间:2017-01-16 20:29:18

标签: ios swift uiactivityindicatorview

我想在自定义类中放置一个活动指示器,以便我可以从任何视图控制器启动/停止它。

以下代码在启动活动指示器但不停止时起作用,我该怎么做?

static func activityIndicatorFunction(view: UIView, targetVC: UIViewController, animate: Bool) {

    var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView()

    if animate == false {
        activityIndicator.stopAnimating()
        UIApplication.shared.endIgnoringInteractionEvents()
    } else {
        activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        activityIndicator.backgroundColor = UIColor(red:0.16, green:0.17, blue:0.21, alpha:1)
        activityIndicator.layer.cornerRadius = 6
        activityIndicator.center = targetVC.view.center
        activityIndicator.hidesWhenStopped = true
        activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.whiteLarge
        view.addSubview(activityIndicator)
        activityIndicator.startAnimating()
        //UIApplication.shared.beginIgnoringInteractionEvents()
    }
}

启动活动指示器的示例,如果我想停止它,则animate参数将为false。

Utils.activityIndicatorFunction(view: view, targetVC: self, animate: true)

3 个答案:

答案 0 :(得分:4)

这是协议扩展的完美候选者。我最近自己这样做了。

首先在文件中创建协议,比如ActivityIndi​​catorPresenter.swift

/// Used for ViewControllers that need to present an activity indicator when loading data.
public protocol ActivityIndicatorPresenter {

    /// The activity indicator
    var activityIndicator: UIActivityIndicatorView { get }

    /// Show the activity indicator in the view
    func showActivityIndicator()

    /// Hide the activity indicator in the view
    func hideActivityIndicator()
}

创建协议扩展(在同一文件中......或不同的文件中)

public extension ActivityIndicatorPresenter where Self: UIViewController {

    func showActivityIndicator() {
        DispatchQueue.main.async {

            self.activityIndicator.activityIndicatorViewStyle = .whiteLarge
            self.activityIndicator.frame = CGRect(x: 0, y: 0, width: 80, height: 80) //or whatever size you would like
            self.activityIndicator.center = CGPoint(x: self.view.bounds.size.width / 2, y: self.view.bounds.height / 2)
            self.view.addSubview(self.activityIndicator)
            self.activityIndicator.startAnimating()
        }
    }

    func hideActivityIndicator() {
        DispatchQueue.main.async {
            self.activityIndicator.stopAnimating()
            self.activityIndicator.removeFromSuperview()
        }
    }
}

然后,任何视图控制器都可以符合协议

class MyViewController: UIViewController, ActivityIndicatorPresenter {

/// Make sure to add the activity indicator
var activityIndicator = UIActivityIndicatorView()

//Suppose you want to load some data from the network in this view controller
override func viewDidLoad() {
    super.viewDidLoad()
    showActivityIndicator() //Wow you can use this here!!!
    getSomeData { data in 
        //do stuff with data
        self.hideActivityIndicator()
    }
}

答案 1 :(得分:1)

我建议将它们作为两个独立的方法实现,也可以将它们添加到UIViewController的扩展名中,如下所示:

UIViewController扩展程序:

extension UIViewController {
    func showActivityIndicator() {
        let activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        activityIndicator.backgroundColor = UIColor(red:0.16, green:0.17, blue:0.21, alpha:1)
        activityIndicator.layer.cornerRadius = 6
        activityIndicator.center = view.center
        activityIndicator.hidesWhenStopped = true
        activityIndicator.activityIndicatorViewStyle = .WhiteLarge
        activityIndicator.startAnimating()
        //UIApplication.shared.beginIgnoringInteractionEvents()

        activityIndicator.tag = 100 // 100 for example

        // before adding it, you need to check if it is already has been added:
        for subview in view.subviews {
            if subview.tag == 100 {
                print("already added")
                return
            }
        }

        view.addSubview(activityIndicator)
    }

    func hideActivityIndicator() {
        let activityIndicator = view.viewWithTag(100) as? UIActivityIndicatorView
        activityIndicator?.stopAnimating()

        // I think you forgot to remove it?
        activityIndicator?.removeFromSuperview()

        //UIApplication.shared.endIgnoringInteractionEvents()
    }
}

我假设你要始终显示/隐藏activityIndicator它到ViewController.view,如果不是,你可能需要让它成为UIView的activityIndi​​cator而不是UIViewController

<强>用法:

例如,考虑您有两个IBAction,第一个显示活动指示器而另一个隐藏它,它们应该是:

@IBAction func show(sender: AnyObject) {
    showActivityIndicator()
}

@IBAction func hide(sender: AnyObject) {
    hideActivityIndicator()
}

答案 2 :(得分:0)

我发现最好只为活动指示器设置一个'标签',然后在停止动画时引用它,使用一个隐藏功能,一个显示为Ahmad建议。 Ahmad F的回答和Guillermo的回答似乎也很好。

在我的Utils.swift文件中显示/隐藏功能:

static func showActivityIndicator(view: UIView, targetVC: UIViewController) {

    var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView()

    activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
    activityIndicator.backgroundColor = UIColor(red:0.16, green:0.17, blue:0.21, alpha:1)
    activityIndicator.layer.cornerRadius = 6
    activityIndicator.center = targetVC.view.center
    activityIndicator.hidesWhenStopped = true
    activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.whiteLarge
    activityIndicator.tag = 1
    view.addSubview(activityIndicator)
    activityIndicator.startAnimating()
    UIApplication.shared.beginIgnoringInteractionEvents()
}

static func hideActivityIndicator(view: UIView) {
    let activityIndicator = view.viewWithTag(1) as? UIActivityIndicatorView
    activityIndicator?.stopAnimating()
    activityIndicator?.removeFromSuperview()
    UIApplication.shared.endIgnoringInteractionEvents()
}

调用show function:

Utils.showActivityIndicator(view: view, targetVC: self)

调用隐藏功能:

Utils.hideActivityIndicator(view: view)