我对我的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
模态?
答案 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
属性,并实现UIViewControllerAnimatedTransitioning
和UIViewControllerAnimatedTransitioning
。
例如:
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)
// }
}