向API请求数据时显示和隐藏模式

时间:2018-11-17 16:07:52

标签: ios swift swift3

我对我的API提出了一些请求,尽管它正在发出请求,但我想显示一个全屏模式,中间有一个微调框,可以覆盖当前场景。

我在情节提要中设置了一个场景,并为该场景指定了控制器:

class LoadingViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
}

在另一个控制器中,我具有以下内容:

class SignInViewController: UIViewController {

    // MARK: Properties

    @IBOutlet weak var submitButton: UIButton!

    // MARK: Actions

    @IBAction func onSubmit(_ sender: Any) {
        // How do I show LoadingViewController as a modal here?
        // Later, how do I hide it?
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

如上所述,当用户单击“提交”按钮时,我想在该控制器上显示全屏模式。然后,当API返回数据时,我想隐藏模式。

如何显示和隐藏LoadingViewController上方的SignInViewController模态?

2 个答案:

答案 0 :(得分:0)

这是一个解决方案,它将在显示的视图之上创建一个简单的加载器视图,

首先,我们需要创建一个负责添加/删除activityIndicator

的类。
class AppLoaderView : UIView{

    fileprivate
    lazy var circularProgressIndicator : UIActivityIndicatorView = {
        let activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
        activityIndicator.center = self.center
        activityIndicator.style = .gray
        activityIndicator.translatesAutoresizingMaskIntoConstraints = false
        activityIndicator.hidesWhenStopped = true
        self.addSubview(activityIndicator)
        return activityIndicator
    }()


    func showSpinning() {
        setupConstraints()
        circularProgressIndicator.startAnimating()
    }

    private
    func setupConstraints() {
        let xCenterConstraint = NSLayoutConstraint(item: self, attribute: .centerX,
                                                   relatedBy: .equal, toItem: circularProgressIndicator,
                                                   attribute: .centerX,
                                                   multiplier: 1,
                                                   constant: 0)
        self.addConstraint(xCenterConstraint)

        let yCenterConstraint = NSLayoutConstraint(item: self, attribute: .centerY,
                                                   relatedBy: .equal, toItem: circularProgressIndicator,
                                                   attribute: .centerY,
                                                   multiplier: 1,
                                                   constant: 0)
        self.addConstraint(yCenterConstraint)
    }


    func removeLoading() {
        circularProgressIndicator.stopAnimating()
    }

}

现在,我们将在viewController上创建一个扩展,它具有两种方法,一种用于显示 LoaderView ,另一种用于删除它,

extension UIViewController{

    private var loaderView : AppLoaderView?{

        if let view =  self.view.subviews.first(where: { $0 is AppLoaderView}) as? AppLoaderView { return view }
        let view = AppLoaderView(frame: self.view.frame)
        view.backgroundColor = .white
        view.autoresizingMask = [.flexibleHeight, .flexibleWidth]
        view.isHidden = true
        return view
    }


    func showLoaderView(){
        if let view = loaderView  {

            self.view.addSubview(view)
            self.view.bringSubviewToFront(view)
            view.isHidden = false
            view.clipsToBounds = true
            view.layoutIfNeeded()
            view.showSpinning()

        }

    }

    func removeLoaderView(){
        if let view = loaderView{
            view.removeLoading()
            view.removeFromSuperview()
            self.view.layoutIfNeeded()
        }
    }
}

就是这样,现在在您的示例中,单击按钮时可以调用self.showLoaderView(),并且一旦API调用返回,您将调用self.removeLoaderView()

将这些添加到项目中的某个位置,然后在任何viewController上都可以将这些方法调用到show/hide的{​​{1}}中。

答案 1 :(得分:0)

要在提供的视图控制器中使用透明背景,请在modalPresentationStyle = .custom类的初始化程序中设置LoadingViewController

要对显示的视图控制器使用自定义过渡,请设置transitioningDelegate类的LoadingViewController属性,并实现UIViewControllerAnimatedTransitioningUIViewControllerAnimatedTransitioning

例如:

class LoadingViewController: UIViewController {

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)

            transitioningDelegate = self        // Required for a custom transition.
            modalPresentationStyle = .custom    // Required for a transparent background.
    }

    // Other setup in your class...
}

extension LoadingViewController: UIViewControllerTransitioningDelegate {

    public func animationController(forPresented presented: UIViewController,
                                    presenting: UIViewController,
                                    source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self
    }

    public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self
    }
}

extension LoadingViewController: UIViewControllerAnimatedTransitioning {

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.25
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

        if isBeingPresented {

            let toView = transitionContext.view(forKey: .to)!
            toView.alpha = 0

            transitionContext.containerView.addSubview(toView)
            UIView.animate(withDuration: 0.25,
                           animations: {
                toView.alpha = 1
            }, completion: { (_) in
                transitionContext.completeTransition(true)
            })

        } else {

            let fromView = transitionContext.view(forKey: .from)!

            UIView.animate(withDuration: 0.25,
                           animations: {
                fromView.alpha = 0
            }, completion: { (_) in
                fromView.removeFromSuperview()
                transitionContext.completeTransition(true)
            })
        }
    }
}

然后,您可以正常显示和关闭自定义LoadingViewController

@IBAction func onSubmit(_ sender: Any) {

    // Present loading view controller.
    self.present(LoadingViewController(), animated: true)

    // Dismiss later in the callback of your API call...
    // API.request {
    //     self.dismiss(animated: true)
    // }
}

这可以达到您想要的效果:
custom transition demo