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