뷰를 전환할 때 모달 뷰(Modal View) 형태로 띄우고 싶을 경우를 위해 포스팅을 해본다. 해놓고 나니 완전 기초 코드였고 도대체 내가 왜 헤맸을까 싶기도 했지만, 처음에는 모달 뷰라는 것이 뭔지도 몰랐고 어버버버 하다가 구글링에 구글링을 거듭해 겨우 해냈던거 ㅜㅜ

 

0. 목표

우선 하려고 하는 바를 정리해보면, 뷰를 2개 만들고, 뷰1에서 버튼을 클릭하면 뷰2가 모달 뷰로 나타나도록 하고 여기에 전환 효과를 살짝 넣어보는 것이다. 그리고 뷰2에서 닫기 버튼을 클릭하면 모달 뷰가 사라지고 다시 뷰1이 나타나게 한다.

 

1. 뷰 2개 생성하기

뷰를 2개 만들어준다. 처음에 프로젝트를 생성할 때 view based project로 생성하면, "프로젝트명ViewController"와 함께 스토리보드 혹은 xib파일이 생성되니 이미 뷰 1개는 만든 것이다. 그리고 뷰 하나 추가는 New File을 생성할 때 View Controller Subclass로 생성하면 .h, .m, .xib파일이 하나씩 생성된다. 이로써 뷰 2개 생성은 완료! 아래 코드에서는 편의상 뷰1의 뷰컨트롤러는 뷰1.h, 뷰1.m라 하고, 뷰2의 뷰컨트롤러는 뷰2.h, 뷰2.m 이라고 하자.

 

2. 뷰1 헤더파일(뷰1.h)에 메서드 선언

- (IBAction)popupSetting;

이 메서드는 뷰1의 스토리보드나 xib에 만들 버튼에 연결할 메서드이다. 헤더파일에 선언 한 다음에 스토리보드나 xib에서 버튼 만들고, control + 클릭해서 touch on inside 오른쪽 원 부분 클릭하고 끌어서 popupSetting에 연결하면 된다.

 

3. 뷰1 구현파일(뷰1.m)에 메서드 정의

#import "뷰2.h"

일단 뷰2를 모달 뷰로 띄울 것이기 때문에, 뷰2.h를 임포트!

- (IBAction)popupSetting
{
    Setting *modalSetting = [[Setting alloc]initWithNibName:@"Setting" bundle:nil];
    [modalSetting setModalTransitionStyle:UIModalTransitionStylePartialCurl]; //모달뷰 전환효과
    [self presentModalViewController:modalSetting animated:YES];
}

메서드 내부에는 딱 저 3줄만 있으면 된다. 심지어 2번째 줄은 전환 효과를 위한 것이고, 전환 효과를 디폴트로 주고 싶으면 굳이 입력하지 않아도 된다.

 

4. 뷰2 헤더파일(뷰2.h)에 메서드 선언

-(IBAction)closeSetting;

모달 뷰로 사용될 뷰2에는 해당 모달 뷰를 닫기 위한 버튼을 만든다. 위의 뷰1에서 했던 것 처럼, 메서드를 생성하고 버튼에 메서드를 연결시키면 된다.

 

5. 뷰2 구현파일에 메서드 정의

-(IBAction)closeSetting
{
    [self dismissModalViewControllerAnimated:YES];
}

모달 뷰 닫기 버튼에 대한 메서드는 심지어 단 한 줄!

 

이렇게 한 후에 빌드를 해보면 시뮬레이터에서 모달 뷰가 아름답게 떴다가 사라졌다가 하는 것을 볼 수 있다. 잘 안 되면 아마 버튼과 메서드를 연결을 시키지 않아서일 가능성이 높음...

 

** 모달뷰 전환효과 더 알아보기

기본적으로 사용할 수 있는 모달 뷰 효과는 총 4가지이다. 위에서 이미 사용한 효과는 종이를 말아 올리는 듯한 효과이고, 아래에 있는 3개 효과도 추가로 있다. (디폴트는 CoverVertical이다.) 

    [modalSetting setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
    
    [modalSetting setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
    
    [modalSetting setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];

 

 

아이폰 수동 메모리 관리와 관련된 기초적인 내용.

그냥 읽으니깐 머리 속에 잘 안 들어와서 정리하는 겸 포스팅!

 

클래스/프로토콜 

메서드 이름

의미

 NSObject Protocol

 retainCount

 객체 혹은 인스턴스 변수가 특정 메모리 공간을 참조하고 있는가를 나타내주는 정수인 레퍼런스 참조 횟수 값을 저장.

 NSObject Class  alloc  생성된 객체에 메모리 공간을 할당. 객체에 메모리가 할당되면 retainCount 메서드에는 1이라는 값이 저장됨.
 NSObject Protocol  retain

 객체가 메모리 공간을 참조하고 있다는 사실을 아이폰에 알림. 메모리 주소는 가지고 있으나 메모리 공간을 사용할 수 없는 어떤 객체가 retain 메서드로 메모리 공간을 참ㅁ조하면 retainCount 메서드의 값은 1만큼 증가.

 NSObject Protocol  release

 객체가 현재 참조하는 메모리 공간을 더는 참조하지 말라는 명령을 내림. 실제로 release 메서드는 retainCount 메서드의 값을 1만큼 감소시킴.

 NSObject Class  dealloc

 메모리 공간을 참조하고 있는 모든 객체가 더는 해당 메모리 공간을 사용하지 말라는 명령을 내림. 어떤 조건이든 retainCount 메서드의 값이 0이 됨.

<참조 횟수를 관리하는 메서드>

 

alloc 메서드와 init 메서드를 통해서 하나의 객체가 생성되면, 사용자는 retain 메서드로 메시지를 보내 새로 생성된 객체가 메모리 공간을 참조하고 이를 사용할 권한을 가지고 있음을 알려주어야 한다(소유권). 또한 release 메서드는 객체가 지정된 메모리 공간을 참조할 필요가 없다는 것을 알려준다(소유권 반환). 정리하면 아래와 같다.

 1. 객체의 참조 횟수 값이 1 또는 그 이상일 경우 아이폰은 메모리 공간을 소유하고 사용할 수 있다.

 2. 객체의 참조 횟수 값이 0이 될 경우, 아이폰은 객체의 메모리 공간에 대한 소유권을 반환받아 할당되었던 메모리 공간을 회수한다.

 

객체의 메모리 할당, 참조, 반환 과정에 따른 참조 횟수의 변화를 보자.

먼저 Foo 클래스를 인스턴스화 하고, 메모리 공간을 할당한 첫 번째 객체 myFooOne을 만들어보자. 

 Foo * myFooOne = [[Foo alloc] init];   //retainCount = 1

이때 myFooOne 객체의 참조 횟수 값은 1이다. 이제 myFooOne 객체를 참조하는 두 번째 객체인 myFooTwo를 생성해보자.

 

 Foo * myFooTwo = myFooOne;    //retainCount = 1

 [myFooTwo retain];                   //retainCount = 2

첫 번째 줄은 myFooTwo 객체가 Foo 클래스를 인스턴스화 했으며 myFooOne 객체를 참조하도록 한다. 하지만 myFooOne 객체의 메모리 공간을 참조한다는 사실을 아이폰이 알고 있지는 않다. 따라서 메모리 공간의 참조 횟수 값은 여전히 1이다.

두 번째 줄에서는 retain 메서드를 사용하여 myFooTwo 객체가 myFooOne 객체와 같은 메모리 공간을 사용한다는 메시지를 myFooTwo 객체에 보낸다. 따라서 해당 메모리 공간의 참조 횟수 값은 2가 된다.

 

이제 myFooOne 객체와 myFooTwo 객체가 더 이상 필요하지 않다고 생가해보자. 이럴 때 사용자는 release 메서드를 사용하여 더는 해당 메모리 주소와 공간을 참조하지 않는다는 메시지를 myFooOne 객체와 myFooTwo 객체에 보낸다.

 [myFooOne release];    //retainCount = 1

 [myFooTwo release];   //retainCount = 0

이때 메모리 공간의 참조 횟수 값은 0이 되며, 아이폰은 myFooOne과 myFooTwo 객체가 함께 사용하던 메모리 공간을 회수한다.

 

 

 

출처 : iOS 앱 개발 시작을 위한 단계별 40개 예제 Objective-C 프로그래밍 (Mc Graw Hill 길벗 출판)