개발을 하다보면 화면에 대한 정보를 알고 싶을때가 있다.
나는 이러한 정보를 아는 방법을 4가지로 분류해서 정리했다
var rootViewController : UIViewController? {
return (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.window?.rootViewController
}
var topMostViewController: UIViewController? {
guard let rootViewController = self.rootViewController else { return nil }
var topMostViewController = rootViewController
while let presentedViewController = topMostViewController.presentedViewController {
topMostViewController = presentedViewController
}
while let parentViewController = topMostViewController.parent {
if parentViewController is UINavigationController {
topMostViewController = parentViewController
} else if let presentedViewController = parentViewController.presentedViewController, presentedViewController != topMostViewController {
topMostViewController = presentedViewController
} else {
break
}
}
if topMostViewController.isViewLoaded && topMostViewController.view.window != nil {
return topMostViewController
} else {
return nil
}
}
반복문을 통해서 최상의 ViewController 판단
var depthViewController : UIViewController? {
get {
var depthViewController = self.topMostViewController
/*
TabBar
*/
if let tabBarController = depthViewController as? UITabBarController {
depthViewController = tabBarController.selectedViewController
}
/*
Navigation
*/
if let navigationController = depthViewController as? UINavigationController {
depthViewController = navigationController.visibleViewController
}
/*
XLPager
*/
if let pagerTapViewController = depthViewController as? ButtonBarPagerTabStripViewController {
let currentIndex = pagerTapViewController.currentIndex
depthViewController = pagerTapViewController.viewControllers[currentIndex]
}
if depthViewController?.isViewLoaded == true && depthViewController?.view.window != nil {
return depthViewController
} else {
return nil
}
}
}
최상의 ViewController의 타입을 판단해서 ChildeViewController 탐색
enum VCContainerType {
case tabBar
case navigationBar
case pager
case vc
}
var containerType : VCContainerType? { get { guard let vc = self.topMostViewController else { return nil } if vc.isKind(of: UITabBarController.self) { return .tabBar } else if vc.isKind(of: UINavigationController.self) { return .navigationBar } else if vc.isKind(of: ButtonBarPagerTabStripViewController.self) { return .pager } else { return .vc } } }
최상의 ViewController의 Container를 판단
위와 같이 코드를 작성하면 필요한 시점에서 ViewController의
정보를 얻을 수 있다. 이런식으로 ViewController의 정보를
얻으면 Model, Banner, LoadingView 표시할때 (ex Network 공통 예외처리)에서 효력을 발휘 할 수 있다.
ex) Modal
class CommonModal { ... func show() { if topMostViewController !== self { topMostViewController?.presentViewController(vc: self, modalTransitionStyle: .crossDissolve, modalPresentationStyle: .overFullScreen, backgroundColor: .clear) } } } ...
ex) Network 공통 예외 처리 모달 표시
func commonAlert(
uiMode : UIMode,
title : String = "앱 오류",
message : String
) {
switch uiMode {
case.NONE, .ONLY_LOADING:
break
case.ONLY_LOGIN, .ALERT_LOGIN:
UserDefaults.standard.setValue("", forKey: "token")
UserDefaults.standard.setValue(false, forKey: "isAutoLogin")
UserDefaults.standard.setValue(0, forKey: "memberId")
MessangerSocketIo.shared.sk_tlanslateBackground()
let vc = ToryWebViewController()
let viewmodel = ToryWebViewModel(path: .LOGIN)
vc.bind(viewmodel)
vc.view.backgroundColor = .togetherWhite
vc.modalTransitionStyle = .crossDissolve
vc.modalPresentationStyle = .fullScreen
(UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.window?.rootViewController = vc
case.ONLY_WARNING, .ALERT_WARNING:
WDModal.Builder()
.setTitle(title)
.setMessage(message)
.setPositiveButton("확인") {
$0.dismiss(animated: true)
}
.build()
.show()
case.ONLY_RESTART, .ALERT_RESTART:
WDModal.Builder()
.setTitle(title)
.setMessage(message)
.setPositiveButton("다시 시작하기") {
$0.dismiss(animated: true)
UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
exit(0)
}
}
.build()
.show()
}
}