[iOS]2계층 UIViewController의 modalViewController 동시에 없애기(dismiss)

위 그림과 같은 상황을 가정해보자. (유저인터페이스가 적합한지는 별개의 문제다. 일단 가정하자.)

로그인뷰(Login View Controller)에서 사용자의 계정을 확인 후, Navigation Controller 를 Modal View 로서 화면에 나타낸다. Navigation Controller 의 설정 버튼을 통해 설정 화면(Settings View Controller)이 Modal View 로 나타나고 이곳에서 특정 이벤트(사용자 계정 log out )가 발생하면, 최초의 로그인 뷰로 돌아간다.

이 경우,  설정화면의 이벤트(ex. log out)에 의해 설정화면(Settings View Controller)과 Navigation Controller 가 함께 사라지는 효과를 구현해야 한다. 어떻게 하면 될까?

쉽게 생각할 수 있는 방은, 먼저 Settings View Controller 에서 dismissModalViewController 를 호출하고,  순차적으로 delegate 를 이용하여 Navigation Controller 에서 dismissModalViewController 를 호출하는 것이다. (참고로 iOS5 이후부터는 presentModalViewController 및 dismissModalViewController 는 deprecated 된다. 대안으로 presentViewController, dismissViewController 를 사용할 것을 권장한다. 정확한 메소드 사용법은 UIViewController Class Reference참조하라.)

이 방법이 제대로 동작할까? 실제로 해보면 쉽게 정상적으로 동작하지 않는 것을 확인할 수 있다. (본인의 개발환경은 OS X 10.6.8, iOS 4.3, XCode 3.2.6 이다.)

먼저 간단하게 위에서 언급한 방법을 구현한 코드를 보자.

Settings View Controller 내부 메소드

<pre>
// settings View controller 에서 사용자 이벤트가 전될되는 메소드
-(IBAction)didPressDone:(id)sender{</pre>
[self.parentViewController dismissModalViewControllerAnimated:YES]; // dismiss SettingsViewController
[delegate userAccountIsDisconnected]; // delegate 를 통하여 Navigation Controller 측에 이벤트를 알림

}
<pre>

코멘트에서와 같이 먼저 Settings View Controller 자신에 dismissModalViewController 를 적용하고, delegate 를 통하여 Navigation Controller 측에 이벤트를 전달한다. (여기서 delegate 사용법은 다루지 않겠다. 생각보다 어렵지 않고 간단하다.)

delegate 메소드가 구현된 Navigation Controller 측 내부 메소드

<pre>
// delegate 메소드
-(void)userAccountIsDisconnected{</pre>
NSLog(@"delegate method");
[self.naviController.parentViewController dismissModalViewControllerAnimated:YES]; //dismiss Navigation Controller

}
<pre>

위 코드는 Navigation Controller 를 dismiss 하여 로그인뷰를 나타나게 하는 것이 목적이다.

실제 위와 같은 코드로 동작을 시켜보면, Settings View Controller  는 정상적으로 사라지지만, Navigation Controller 화면은 사라지지 않아 로그인뷰가 화면에 나타나지 않는다.

디버그를 해보면 다음과 같은 에러메시지를 확인할 수 있다.

attempt to dismiss modal view controller whose view does not currently appear”

Settings View Controller 를 없애는 작업 (dismiss settings view controller)가 완전히 완료되지 않은 시점에서, 다른 뷰를 없애는 작업(dismiss navigation controller)를 하려고 하니 문제가 발생하는 것이다.

Settings View Controller 를 없애는 작업이 완전히 완료가 되고 화면이 안정적으로 구조화 된 후에 Navigation Controller 를 없앤다면 문제가 발생하지 않겠지만, 이는 화면에 별도의 이벤트(버튼)가 필요할 수도 있으므로 우리가 바라는 UI는 아니다.

그럼 해결책은 뭘까? 여러가지 방법이 있겠지만, Settings View Controller 를 없애는 작업을 수행하지 않은 채 바로 Navigation Controller 를 없애는 것이 하나의 해결책이다. 이렇게 되도 정상적으로 Settings View Controller 는 사라지고 메모리에서도 dealloc 된다.

하위층의 View Controller를 사라지게(dismiss)하면, 그 상위의 뷰들도 자연히 사라지는 듯 하다.

코드는 다음과 같이 Settings View Controller 에서의 설정뷰 자신을 없애는 부분을 생략하고 사용자 이벤트를 바로 Navigation Controller 측에 넘겨주면 된다.

<pre>
// settings View controller 에서 사용자 이벤트가 전될되는 메소드
-(IBAction)didPressDone:(id)sender{</pre>
//[self.parentViewController dismissModalViewControllerAnimated:YES]; // dismiss SettingsViewController
[delegate userAccountIsDisconnected]; // delegate 를 통하여 Navigation Controller 측에 이벤트를 알림

}
<pre>

실제 해결책은 생각보다 간단하였지만  UIViewController 의 계층 구조 및 라이프 사이클 등에 대해 좀 더 정확하게 파악할 필요가 있다.

Advertisements
Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: