아이폰어플개발정보2010. 6. 22. 09:55
[Objective-C]Autosize 2번째
화면이 회전할때 처리방식은 여러가지 방식이 있는데 이전 포스트에서는 좌표들이 바뀌는 것에 대한 포스트를 했었다.
이번에는 아예 다른 뷰를 가지고 다르게 구성하는것을 살펴 보겠다.

이 방법은 매우 복잡한 인터페이스를 사용하는 경우에 어울리는 방법이다. 
가로보기와 세로보기뷰를 따로 설계하고 하드웨어가 회전했을 경우 뷰를 전환하게 하는 것이다.
양쪽 뷰의 컨트롤 들에게 동일한 액션을 설계해 주어야 하며, 이렇게 될 경우 중복 코드들이 생기게 된다.

일단  View-Based프로젝트를 Swap이라는 이름으로 생성한다. 이 애플리케이션에서 만들려는 인터페이스는 기술의 복잡성을 제대로 파악할 수 있을만큼 복잡하진 않다. 과정을 분명히 하기 위해서 매우 간단한 인터페이스를 사용할 것이다. 이 애플리케이션은 시작할 때 세로보기모드로 동작한다. 두개의 버튼이 있는데 Foo, Bar 버튼이다. 각 버튼을 탭하게 되면 해당 버튼은 사라지게 된다.
폰을 회전시키면 가로보기 모드방향에서 완전히 다른 뷰로 전환된다. 같은 이름을 가진 2개의 버튼이 있기 때문에 사용자는 서로 다른 두 종류의 뷰를 볼수 있다는 사실을 알아차리지 못한다. 2개의 버튼도 탭하면 사라지게 된다.
각 뷰에 대해 모두 2개씩의 버튼을 만들어야 한다. 또한 아웃렛이 하나 이상의 객체를 가리킬 수 없기 때문에 총 4개의 아웃렛을 별도로 정의해야 한다.
버튼에 쓸 아웃렛 외에도, 다른 두가지 버전의 뷰를 가리키는데 필요한 아웃렛이 두개 더 필요하다. 뷰를 하나만 사용하는 경우라면, 부모 클래스의 뷰 속성만 있으면 된다. 하지만, 런타임에 뷰의 값을 변경해야 하기 때문에, 두가지 뷰를 모두 얻을 수 있는 방법이 확실히 있어야 한다. 이런 이유로, 두개의 UIView아웃렛이 필요한 것이다.
버튼을 누르면 특정한 액션을 수행해야 한다. 따라서 버튼에는 적어도 하나의 액션 메서드가 필요하다. 어떤 버튼이 눌리든지 그 동작을 모두 처리할 액션 메서드를 하나 설계해 보겠다.

SwapViewController.h

#import <UIKit/UIKit.h>
#define degressToRadians(x) (M_PI * (x) / 180.0)

@interface SwapViewController : UIViewController {
UIView *landscape;
UIView *portrait;
UIButton *landscapeFooButton;
UIButton *portraitFooButton;
UIButton *landscapeBarButton;
UIButton *portraitBarButton;
}

@property (nonatomic, retain) IBOutlet UIView *landscape;
@property (nonatomic, retain) IBOutlet UIView *portrait;
@property (nonatomic, retain) IBOutlet UIButton *landscapeFooButton;
@property (nonatomic, retain) IBOutlet UIButton *portraitFooButton;
@property (nonatomic, retain) IBOutlet UIButton *landscapeBarButton;
@property (nonatomic, retain) IBOutlet UIButton *portraitBarButton;

-(IBAction) buttonPressed:(id)sender;

@end


degreesToRadians() 메소드의 경우 각도를 라디안으로 변환하는 단순 매크로 이다. 
나머지 부분들은 이미 친숙한 것들이다. 이제 아웃렛 구현이 끝난샘이니 인터페이스 빌더로 가서 필요한 두개의 뷰를 빌드해 보자. 

2개의 뷰가 필요하다. 템플릿을 통해 제공되는 뷰는 크기를 조절 할 수 없기 때문에 사용하지 않을 것이다. 대신에 템플릿이 제공하는 뷰 2개를 삭제하고 새로운 2개의 뷰를 생성하자.
2개의 뷰를 추가로 생성해 준다.
 
뷰는 라이브러리 창 하단부에서 찾을 수 있다.
 
File's Owner 에서 Control 드래그 하여 각각의 뷰를 아웃렛에 연결해 준다. 또한 Portrait의 경우 기본적으로 보여야할 view에도 연결해준다. 그렇게 되면 처음에 보여지게 될 뷰로 설정 된다.
 
LandScape 역시 같은 방식으로 뷰 연결을 해 준다.
 
LandScape 의 경우 뷰 사이즈는 320 * 460인데 이를 480 * 300으로 변경해야 한다.
 
이제 각각의 뷰에 버튼 2개씩을 드래그하여 놓아보자.
125 * 125 로 적당한 위치로 배치하고 이름을 정해 준다.
 
 
 
버튼 역시 위에서 정해둔 아웃렛에 다 연결해 주게 된다.
 
이제 각각의 버튼에 Connection창을 열어서 Touch Up Inside에 buttonPressed IBAction을 할당 해 준다.

SwapViewController.m

#import "SwapViewController.h"

@implementation SwapViewController
@synthesize landscape;
@synthesize portrait;
@synthesize landscapeFooButton;
@synthesize landscapeBarButton;
@synthesize portraitFooButton;
@synthesize portraitBarButton;

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
if(toInterfaceOrientation == UIInterfaceOrientationPortrait){
self.view = self.portrait;
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degressToRadians(0));
self.view.bounds = CGRectMake(0.0, 0.0, 300.0, 480.0);
}else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft){
self.view = self.landscape;
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degressToRadians(-90));
self.view.bounds = CGRectMake(0.0, 0.0, 460.0, 320.0);
}else if(toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown){
self.view = self.portrait;
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degressToRadians(180));
self.view.bounds = CGRectMake(0.0, 0.0, 300.0, 480.0);
}else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeRight){
self.view = self.landscape;
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degressToRadians(90));
self.view.bounds = CGRectMake(0.0, 0.0, 460.0, 320.0);
}
}

-(IBAction) buttonPressed:(id)sender{
if(sender == portraitFooButton || sender == landscapeFooButton){
portraitFooButton.hidden = YES;
landscapeFooButton.hidden = YES;
}else{
portraitBarButton.hidden = YES;
landscapeBarButton.hidden = YES;
}
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)viewDidUnload {
self.landscape = nil;
self.portrait = nil;
self.landscapeFooButton = nil;
self.landscapeBarButton = nil;
self.portraitFooButton = nil;
self.portraitBarButton = nil;
[super viewDidUnload];
}

- (void)dealloc {
[landscape release];
[landscapeFooButton release];
[portraitFooButton release];
[landscapeBarButton release];
[portraitBarButton release];
    [super dealloc];
}

@end

willRotateToInterfaceOrientation 메소드는 회전이 일어나기 직전에 호출되는 메소드이다. 이 메소드를 통해 회전 방향을 알아내어 뷰 속성을 새로운 방향에 적합하 가로보기 또는 세로보기 모드로 정하게 된다. 그 후 코어 그래픽스 프레임워크에 포함왼 CGAffineTransformMakeRotation을 사용해 회전변환을 생성했다. 여기서의 변환은 객체의 크기, 위치, 각도의 변경에 대한 수학적인 표현이다.
일반적으로 아이폰은 회전하면 자동으로 변환된 값을 설정해 준다. 그러나 여기서는 새로운 뷰로 교체가 일어났기 때문에 아이폰이 혼동을 일으키지 않도록 값이 정확한지 확인할 필요가 있다.
뷰의 변환 속성이 설정될때마다 willRotateToInterfaceOrientation 메소드가 이런 역할을 한다. 뷰가 회전되면 프레임을 조정하여 윈도우가 현재 방향에 어울리게 설정될 수 있도록 조정된다.
shouldAutorotateToInterfaceOrientation 메소드의 경우 우리가 모든 방향에 대한 회전을 제공한다는 사실을 아이폰에게 알려주기 위해서 무조건 YES를 리턴하는 메소드가 되었다. 또한 간단한 메모리 클린업을 위해 dealloc메소드도 수정되었다.
 
회전하는 순간의 캡쳐화면
 


출처 : http://blog.naver.com/PostView.nhn?blogId=khagaa&logNo=30086764336

'아이폰어플개발정보' 카테고리의 다른 글

과제B - 간단한 코딩 해보기  (0) 2010.06.22
과제A - Hello Stanford 찍어보기  (0) 2010.06.22
[Objective-C]Autosize 2번째  (0) 2010.06.22
[Objective-C] AutoSize 속성  (0) 2010.06.22
[ObjectiC]액션시트, 경고창  (0) 2010.06.22
[Objective-C] 태그  (0) 2010.06.22
Posted by 오늘마감

댓글을 달아 주세요