Roen의 iOS 개발로그

modal을 닫지 않고 탭을 이동했다가 다시 돌아와 modal을 닫으면, view가 보이지 않는 문제

by Steady On

문제 상황

modal로 띄운 view가 Tab bar를 가리지 않도록 parentView의 바탕에 Navigation Controller로 깔아주고, modal의 modalPresentationStyleoverCurrentContext로 주었다. 그런데 이 modal을 닫지 않고 다른 탭으로 이동했다가 돌아와서 modal을 닫으니까 view가 텅 비어있었다. 그래서 view hierarchy를 확인해보니 modal view 아래에 있어야 할 view가 없었다.

 

 

파헤치기

바로 구글링....! stackoverflow에서 같은 문제를 겪은 사람을 찾을 수 있었다.

https://stackoverflow.com/questions/50015547/remove-black-background-when-switching-tab-of-uitabbarcontroller

답변으로 viewDidLoaddefinesPresentationContext = true 명령어를 추가해주라고 하는데... 이게 뭔지, 원인이 무엇인지 알아보았다.

definesPresentationContext는 UIViewController의 인스턴스 프로퍼티이고, 정의는 다음과 같다.

 

뷰 컨트롤러 또는 하위 구성원 중 하나가 뷰 컨트롤러를 표시할 때 이 뷰 컨트롤러의 뷰가 포함되는지 여부를 나타내는 부울 값이다.

 

.... 좀 더 자세히 살펴보자.

 

Discussion

When using the UIModalPresentationStyle.currentContext or UIModalPresentationStyle.overCurrentContext style to present a view controller, this property controls which existing view controller in your view controller hierarchy is actually covered by the new content. When a context-based presentation occurs, UIKit starts at the presenting view controller and walks up the view controller hierarchy. If it finds a view controller whose value for this property is true, it asks that view controller to present the new view controller. If no view controller defines the presentation context, UIKit asks the window’s root view controller to handle the presentation.

currentContextoverCurrentContext 스타일을 사용해서 view controller를 띄울 때, 이 프로퍼티는 view controller 계층에 존재하는 view controller가 실제로 새로운 컨텐트로 덮일 것인지를 컨트롤 한다. context 기반의 presentation이 발생하면, UIKit은 지금 나타나는 view controller에서 시작해서 view controller 계층을 올라간다. 그러다가 이 프로퍼티가 true인 view controller를 찾으면, 그 view controller에게 새로운 view controller를 나타낼 것을 요청한다. 프리젠테이션 컨텍스트를 정의하는 view controller가 없으면 UIKit은 window의 root view controller에서 프리젠테이션을 처리하도록 요청한다.

 

그러니까 정리하자면, 이건 currentContext에 관련된 스타일을 사용하면 생기는 문제다. 해당 스타일을 사용해서 view를 present 하면 이 view가 어디를 기반으로 해서 나타날 것인지를 계산하게 되는데, 아무 설정도 하지 않는다면, window의 root view controller를 기반으로 해서 나타난다는 거다.

 

위 이미지로 보면, 내 경우는 Tab Bar Controller - Navigation Controller - Recommand Beer View Controller 순으로 view가 이어져 있는데, 아무 설정도 하지 않고 currentContext 기반의 모달을 present하면 가장 밑바닥에 있는 root view인 Tab Bar Controller에서 처리가 된다는 뜻이다. 아래의 view hierarchy를 보면 더 명확하게 알 수 있다.

modal의 띄워진 상태에서 Tab을 이동했다가 돌아왔을 때의 view hierarchy

 

해결하기

그래서 이 present가 어떤 view controller를 기반으로 처리될지를 명시하는 프로퍼티가 definesPresentationContext이다. 이 속성을 원하는 view controller에서 true로 명시해주면, 해당 view controller에서 present를 처리하게 된다. 그래서 Recommand Beer ViewviewDidLoad에 다음 코드를 추가해주면,

self.definesPresentationContext = true

위와 같이 Tab을 이동했다가 돌아와도 Recommand Beer View가 사라지지 않고 남아 있는 것을 확인할 수 있다.

 
 
 

 

블로그의 정보

Roen의 iOS 개발로그

Steady On

활동하기