FirstViewController在另一个SecondViewController上,可单击SecondViewController

时间:2018-10-29 09:02:55

标签: ios swift uikit

我正在尝试创建通用警报,该警报出现在最顶部的视图控制器上,而底部的ViewController仍可单击。 该警报只是20点高度的状态行,通知用户网络可达性。如何使UIViewController不能与用户交互?

1 个答案:

答案 0 :(得分:2)

请注意,我没有使用Storyboard或XIB 如果您的目标是iOS11及更高版本,则在使用自动布局代码时需要使用safeAreaLayoutGuide

解决方案有两个方面。

首先,创建一个Base View Controller,并使所有需要显示警报的View Controller从该Base View Controller扩展。

然后创建一个新的swift文件,它是NSObject的子类。假设NetworkAlerter.swift并复制粘贴以下代码(适当)

import UIKit

class NetworkAlerter: NSObject {

var window :UIWindow? = UIApplication.shared.keyWindow

var alertShowingConstraint : NSLayoutConstraint?
var alertHidingConstraint : NSLayoutConstraint?

var closeTimer : Timer? = nil

public lazy var networkIndicatorLabel : UILabel = {
    let label : UILabel = UILabel(frame: .zero)
    label.translatesAutoresizingMaskIntoConstraints = false
    label.textAlignment = NSTextAlignment.center
    return label
}()


override init() {
    super.init()
    createSubviews()
}

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

deinit {
    print("Time to deinit")
    networkIndicatorLabel.removeFromSuperview()
}

func createSubviews() {
    guard let window = window else {
        print("Some thing wrong with Window initialization!!")
        return
    }
    window.addSubview(networkIndicatorLabel)
    addAutolayout()
}

func addAutolayout() {
    guard let window = window else {
        print("Some thing wrong with Window initialization!!")
        return
    }
    alertShowingConstraint = networkIndicatorLabel.topAnchor.constraint(equalTo: window.topAnchor)
    alertHidingConstraint = networkIndicatorLabel.bottomAnchor.constraint(equalTo: window.topAnchor)
    alertHidingConstraint?.isActive = true
    networkIndicatorLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
    networkIndicatorLabel.leadingAnchor.constraint(equalTo: window.leadingAnchor).isActive = true
    networkIndicatorLabel.trailingAnchor.constraint(equalTo: window.trailingAnchor).isActive = true
}

func showNetworkAlerter(networkAvailable: Bool) {
    guard let window = window else {
        print("Some thing wrong with Window initialization!!")
        return
    }
    invalidateAndKillTimer()
    closeTimer = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(dismissNetworkAlerter), userInfo: nil, repeats: false)

    if networkAvailable {
        networkIndicatorLabel.text = "Available"
        networkIndicatorLabel.backgroundColor = UIColor.green
    } else {
        networkIndicatorLabel.text = "Not Available"
        networkIndicatorLabel.backgroundColor = UIColor.red
    }

    window.layoutIfNeeded()
    UIView.animate(withDuration: 0.5, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 1.0, options: .curveEaseOut, animations: {
        if (self.alertHidingConstraint?.isActive)! {
            self.alertHidingConstraint?.isActive = false
        }
        if !(self.alertShowingConstraint?.isActive)! {
            self.alertShowingConstraint?.isActive = true
        }
        window.layoutIfNeeded()
    }, completion: { _ in
    })
}

@objc func dismissNetworkAlerter() {
    invalidateAndKillTimer()
    guard let window = window else {
        print("Some thing wrong with Window initialization!!")
        return
    }
    window.layoutIfNeeded()
    UIView.animate(withDuration: 0.5, animations: {
        if (self.alertShowingConstraint?.isActive)! {
            self.alertShowingConstraint?.isActive = false
        }
        if !(self.alertHidingConstraint?.isActive)! {
            self.alertHidingConstraint?.isActive = true
        }
        window.layoutIfNeeded()
    }) { (done) in
    }
}

// MARK:- Timer Related
private func invalidateAndKillTimer() -> Void {
    if (closeTimer != nil) {
        closeTimer?.invalidate()
        closeTimer = nil
    }
}

}

然后移回基本视图控制器。在顶部复制以下内容

var networkAlertLauncher : NetworkAlerter? = nil

,然后在Base View Controller中找到合适的位置并粘贴以下内容:

func showAlertBar(networkAvailabilityStatus: Bool) -> Void {
        if networkAlertLauncher != nil {
            networkAlertLauncher = nil
        }

        networkAlertLauncher = NetworkAlerter()
        networkAlertLauncher?.showNetworkAlerter(networkAvailable: networkAvailabilityStatus)
    }

现在,您可以从Base View Controller扩展的所有视图控制器中访问showAlertBar函数。您可以这样调用它: self.showAlertBar(networkAvailabilityStatus: false)self.showAlertBar(networkAvailabilityStatus: true)