- 创建根控制器管理类
class RootViewController: UIViewController {
static let shared = RootViewController()
var rootController: UIViewController? {
get {
let scences = UIApplication.shared.connectedScenes
let windowScence = scences.first as? UIWindowScene
let window = windowScence?.windows.first
let viewController = window?.rootViewController
return viewController
}
}
}
- 扩展里实现弹窗和消失事件
extension RootViewController {
func present<Content: View>(@ViewBuilder content: () -> Content) {
let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
toPresent.modalPresentationStyle = .overCurrentContext
toPresent.modalTransitionStyle = .crossDissolve
toPresent.view.backgroundColor = .clear
toPresent.rootView = AnyView(content())
rootController?.present(toPresent, animated: false)
}
func dismiss(animated: Bool = true) {
rootController?.dismiss(animated: animated)
}
}
- 写一个要弹的窗口视图,弹出与消失动画可根据需求去设置
struct PresentTestView: View {
@State var isShow: Bool = false
var body: some View {
ZStack {
Color.black.opacity(0.3).ignoresSafeArea().onTapGesture {
// 内容先消失
withAnimation {
isShow = false
}
// 随后页面消失
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
RootViewController.shared.dismiss(animated: true)
}
}
Text("我是根控制器上的弹窗")
.font(.system(.title))
.padding(15)
.frame(width: 300, height: 200)
.foregroundColor(.black)
.background(Color.yellow)
.cornerRadius(10)
.scaleEffect(isShow ? 1 : 0)
.rotationEffect(.degrees(isShow ? 360 : 0))
.opacity(isShow ? 1 : 0)
}
.onAppear {
withAnimation(.easeIn(duration: 0.2)) {
isShow = true
}
}
}
}
- 最后,可在任何地方(View 或 ViewModel)调用根控制器管理类弹出你所写的弹窗视图
RootViewController.shared.present {
PresentTestView()
}