본문 바로가기

개발지식

UIKit) 최상단을 계속 유지하는 토스트 메세지 만들기

반응형

기존에 토스트 메세지를 만들고자 했을 때 다음과 방법을 사용했었다.

guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else { return }

먼저 사용하는 윈도우 중 key 윈도우를 찾는다.

그리고 해당 윈도우에 최상위 뷰를 찾아서 그곳에 토스트 메세지를 사용했을 것이다. 

이렇게 토스트 메세지를 만들면 문제가 발생한다.
먼저 토스트 메세지를 띄우는 순간에는 UIWindow 내에서는 최상위이겠지만 FullScreenConver를 띄우는 순간
최상위 뷰는 토스트 메세지가 아닌 FullScreenConver로 띄운 뷰가 되어버리는 것이다. 

 

때문에 다음과 같이 토스트 메세지가 사라졌다. 

 

문제 해결

guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else { return }

여기서 기존에 사용하는 코드에서 힌트를 얻었다.  isKeyWindow는 윈도우가 키 윈도운지를 알아내는 Bool 값이다. 그렇다면 UIWindow를 여러 개 만들 수 있다는 의미이기도 하다. 추가적으로 키 윈도우는 한 번에 하나의 윈도우만 키 윈도우가 될 수 있다. 

 

 

guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return }

 

첫 번째로 현재 앱에서 활성된 모든 Scene 목록 중 연결된 Scene을 찾아야한다. 

UIWindow는 하나의 UIWIndowScene에 포함되어야 한다. 대부분의 iOS 앱은 하나의 UIWindowScene을 가지지만 iPad와 같은 경우는 멀티 윈도우를 지원하기 때문에 UIWindowScene 역시 여러 개가 될 수 있다. 

 let window = UIWindow(windowScene: scene)
 window.windowLevel = .alert + 1

UIWindow는 하나의 windowScene에 들어가야 하기 때문에 init 시에 다음과 같이 넣어주어야 한다.
또한 windowLevel은 윈도우의 Z축 위치를 결정하는 속성이다. 

 

windowLevel에는 3가지가 존재한다. normal, statusBar, alert

- normal은 일반적인 UI 윈도우 레벨

- statusBar는 메인 윈도우의 위에 표시되지만 .alert보다는 낮은 레벨

- alert는 status bar의 위에 표시되는 레벨이다. 

 

때문에 토스트 메세지를 제일 띄우는게 목적이었으니 alert로 해주었다. 

 

 

   window.rootViewController = UIViewController()
        window.rootViewController?.view.addSubview(hostingController.view)
        window.isHidden = false
        self.window = window

 

그리고 window를 만들어주었으니 이제 window에 들어갈 view를 붙여주면 토스트 메세지를 만들 수 있는 것이다. 

 

이렇게 별도의 UIWindow를 만들었기 때문에 기존 UIWindow에서의 화면 전환이라는 전혀 관계 없는 사이가 되었다. 결과적으로 제일 위에 있는 토스트 메세지를 만들 수 있었던 것이다. 

 

추가적으로 뷰 계층을 보면 다음과 같다. 만들었던 것 처럼 하나의 UIWIndowScene에 두 개의 UIWindow가 존재하고 있는 것을 볼 수 있다.

반응형