ProgrammingInObjectiveC:Chapter 21

From 흡혈양파의 번역工房
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
21장
아이폰 응용 프로그램 만들기

21장 :: 아이폰 응용 프로그램 만들기

이 장에서 간단한 아이폰 응용 프로그램을 두개 개발할것이다. 첫 번째 개발에서는 인터페이스 빌더를 사용할 때 반드시 알아야 할 할 개념들을 설명한다. 여기에는 연결 짓기, '델리게이트', '아웃렛', '액션' 등을 이해하기가 포함된다. 두 번째에서는 분수 계산기를 만들 것이다. 이 프로그램을 만들 때 첫 번째 프로그램을 개발하며 배운 내용과 이 책에서 배운 내용을 모두 동원할 것이다.


아이폰 SDK

아이폰 응용 프로그램을 만들려면 Xcode 와 아이폰 SDK 를 인스톨해야 한다. 이 SDK 는 애플의 웹사이트에서 무료로 구할 수 있다. SDK 를 다운로드하려면 먼저 애플 개발자로 등록해야 한다. 이 역시 무료다. http://developer.apple.com 에서 적절한 지점을 찾아 들어가면 각 링크를 발견할 수 있을 것이다. 이 사이트에 익숙해지면 여러모로 유용하다. 이 사이트에 있는 링크 중 여러분에게 유용한 것을 부록 D 「참고자료」에 정리했다. 이 장에서 설명하는 내용은 Xcode 3.1.1 과 아이폰 OS 2.1 에 해당하는 아이폰 SDK 를 기반으로 한다. Xcode 나 아이폰 SDK 의 추후 버전은 모두 여기서 설명하는 것과 호환될 수 있을 것이다.


첫 번째 아이폰 응용 프로그램

첫 번째 프로그램은 아이폰 화면에 검은색 창을 띄우고 사용자가 누를 버튼을 넣는다. 버튼을 누르면 텍스트가 표시된다.


objc2_notice_01
두 번째 프로그램이 훨씬 재미있다! 첫 번째 프로그램에서 배운 지식을 활용하여 분수 연산을 수행하는 간단한 계산기를 만들 것이다. 초반에 만든 Fraction 클래스와 수정된 Calculator 클래스를 쓰면 된다. 이번에는 계산기가 분수를어 떻게 다뤄야 할지를 알아야 한다.


첫 번째 프로그램에 바로 들어가자. 모든 내용을 설명하기에는 지면이 부족하기 때문에, 이 장에서는 상세하게 설명하지는 않는다. 그 대신 다른 코코아관련 도서 또는 아이폰 프로그래밍 도서에서 더 많은 개념을 학습할 수 있도록 각 단계를 훝어보며, 필요한 기반을 제공할 것이다.

그림 21.1 은 아이폰용 첫 번째 응용 프로그램이 아이폰 시뮬레이터 에서 동작하는 모습이다(시뮬레이터 에 대해서는 곧 더 설명할 것이다).

이 프로그램은 '1' 이라는 이름이 불은 버튼을 누르면 해당 숫자가 화면에 표시되도록 디자인 되었다(그림 21.2 가 결과이다). 이게 이 프로그램이 하는 모든 일이다! 이 간단한 응용 프로그램을 통해 두 번째 분수 계산 프로그램을 만드는 데 필요한 모든 기반을다진다.

그림 21.1 첫 번째 아이폰용 응용 프로그램
그림 21.2 아이폰 응용 프로그램을 실행한 결과


Xcode 와 인터페이스 빌더를 사용하여 응용 프로그램과 사용자 인터페이스를 생성할 것이다. 지금까지 이 책을 읽어 왔고, Xcode 를 사용하여 프로그램을 입력하고 테스트해 왔다면 이제 Xcode 는 꽤 익숙할 것이다. 이미 말했듯이, 인터페이스 빌더는 표, 레이블, 버튼 같은 UI 항목을 아이폰 스크린과 유사한 윈도에 배치시켜서 사용자 인터페이스를 디자인하는 도구다. 여느 강력한 개발 도구와 마찬가지로 인터페이스 빌더를 잘 사용하려면 먼저 익숙해져야 한다.

애플은 아이폰 시뮬레이터를 아이폰 SDK에 넣어 배포한다. 시뮬레이터는 아이폰의 홈스크린, 사파리 웹 브라우저, 주소록 프로그램 등을 포함하며 아이폰 환경의 대부분을 복제한다. 시뮬레이터를 사용하면 응용 프로그램을 더 쉽게 디버그할 수 있다. 즉,시뮬레이터만 있다면 응용프로그램의 각각의 버전을 실제 아이폰장치에 다운로드해 거기서 디버그하지 않아도 된다. 이를 통해 많은 시간과 노력을 절약할 수 있다.

아이폰 장치에서 응용 프로그램을 실행하려면 먼저 아이폰 개발자 프로그램에 등록하고 일정 금액을 애플에 지불해야 한다(이 글을 쓰고 있는 지금은 99 달러다). 그러면 아이폰에 응용 프로그램을 설치하고 테스트 하도록 해주는 iPhone Development Certificate 를 얻을 수 있는 활성화 코드를 받게 된다. 안타깝지만, 개인의 아이폰에서만 사용할 응용 프로그램을 개발할 때도 이 과정을 거쳐야 한다. 우리가 개발한 프로그램은 아이폰 장치가 아니라 아이폰 시뮬레이터에서만 로드되고 테스트 된다는 점을 유념하자.


아이폰 응용 프로그램 프로젝트 새로 만들기

첫 번째 응용 프로그램을 개발하는 시점으로 다시 돌아가자. 아이폰 SDK 를 설치하고 Xcode 를 실행하자. File 메뉴에서 New Project 를 선택한다. 아이폰 OS 아래에서 Application 을 선택하자(만일 왼쪽 부분에서 이게 나타나지 않는다면, 아이폰 SDK 를 설치하지 않았다는 의미다). 이제 윈도가 그림 21.3과 같아 보일 것이다.

다양한 종류의 응용 프로그램을 개발할 때 시작점이 되어 주는 템플릿들이 있다. 표 21.1 에 이것들을 정리해 놓았다.

그림 21.3 새 아이폰 프로젝트 시작하기


응용 프로그램 종류 설명
Navigation-Bases 내비게이션 컨트롤러를 사용하는 응용 프로그램. 이런 응용 프로그램으로는 주소록이 있다.
OpenGL ES 게임과 같은 Open GL 그래픽 기반 응용 프로그램.
Tab Bar 탭 바를 사용하는 응용 프로그램. 한 예로 아이팟 프로그램이 있다.
Utility 앞뒤 면이 있는 응용 프로그램. 주식 프로그램이 그 예다.
View-Based 뷰 기반 프로그램. 이 뷰에 그림을 그리고, 윈도에 이 뷰를 표시한다.
Window-Based 메인 아이폰 윈도만 가지고 시작하는 프로그램. 이 메인 윈도에서 어느 프로그램이든 시작할 수 있다.
표 21.1 아이폰 응용 프로그램 템플릿


New Project 윈도로 돌아가서 맨 오른쪽 위에서 Window-based Application 을 선택하고 Choose 버튼을 누르자. 다음에 뜨는 창에 (Save As 상자에) 프로젝트 이름을 iPhone_1 로 입력하고 save 를 클릭하자. 응용 프로그램의 이름도 이 텍스트로 설정된다. Xcode로 만든 이전 프로젝트에서 익속히 보았듯이, 새 프로젝트는 여러분이 사용할 파일들의 템플릿을 보유한 채로 생성될 것이다. 그림 21.4 에서 이를 확인할 수 있다.

그림 21.4 새 아이폰 프로젝트 iPhone_1 이 생성되었다.


여러분이 어떻게 설정하고 이전에 Xcode를 어떻게 사용했는지에 따라, 윈도가 그림 21.4 와 완전히 같지는 않을 수 있다. 현재 여러분의 레이아웃을 그대로 계속 사용하거나, 이 그림과 유사하도록 변경해도 무방하다.

Xcode 맨 위의 좌측에 현재 선택한 SDK 와 Active Configuration 을 표시해 주는 드롭다운 버튼이 보일 것이다. 현재 우리는 아이폰에서 직접 돌아갈 프로그램을 개발하는 것이 아니다. 그러니 SDK 가 프로그램을 아이폰 시뮬레이터로 실행시키도록 설정하고 Configurataion 을 Debug 로 설정해 줘야 한다. 만일 드롭다운 버튼이 Simulator | Debug 로 되어 있지 않다면 그림 21.5 처럼 적절한 옵션을 선택해 주자.

그림 21.5 SDK 와 Configuration 옵션이 설정된 iPhone_1 프로젝트


코드 입력하기

이제 프로젝트 파일을 일부 수정해 줄 차례다. project-name AppDelegate.m 과 project-name AppDelegate.h 가 이미 생성되어 있음에 주목하자. 우리 프로젝트의 경우에는 project-name 이 iPhone_1 이다. 우리가 만드는 윈도 기반 응용 프로그램의 경우 다양한 버튼과 레이블의 처라는 project-name AppDelegate 클래스에 '델리케이트(delegate, 위임)'된다. 우리 프로젝트에서는 iPhone_1AppDelegate 라는 클래스에 위임된다. 이 클래스에 버튼을 누르거나 슬라이더를 움직이는 식의, 아이폰 윈도에서 일어나는 '액션(action)' 에 응답하는 메서드를 작성할 것이다. 앞으로 보게 되겠지만, 인터페이스 빌더에서 이 컨트롤들과 대응하는 메서드를 실제로 연결하게 될것이다.

또한, 이 클래스는 아이폰 윈도에 있는 몇몇 컨트롤에 값이 대응되는 인스턴스 변수도 포함할 것이다. 이런 인스턴스 변수로는 레이블 이름이나,수정 가능한 텍스트 박스에 표시되는 텍스트가 있다. 이 변수들은 '아웃렛(outlet) '이라고 한다. 액션 루틴과 마찬가지로 인터페이스 빌더에서 이 인스턴스 변수들과 아이폰의 윈도 안에 있는 실제 컨트롤을 연결해 준다.

첫 번째 프로그램에서 1 이라고 이름 불은 버튼을 누를 때 이 액션에 응답할 메서드가 필요하다. 또한, 우리는 아이폰 윈도의 맨 위에 레이블을 만들었는데, 여기에 표시할 텍스트를 담을 아웃렛 변수도 필요하다.

iPhone_lAppDelegate.h 파일을 수정하여 새 UILabel 변수인 display 를 추가하고, 버튼을 누를 때 응답하도록 click1: 액션 메서드를 선언한다. 인터페이스 파일은 프로그램 21.1 처럼 되어야 한다(파일의 앞부분에 자동으로 들어가는 주석은 생략했다).


프로그램 21.1 iPhone_1AppDelegate.h


#import <UIKit/UIKit.h>

@interface iPhone_1AppDelegate : NSObject <UIApplicationDelegate>
    UIWindow *window;
    UILabel *display;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UTLabel *display;

- (IBAction) click1: (id) sender;

@end


아이폰 응용프로그램에서 <UIKit/UIKit.h> 가 헤더파일을 임포트한다는 데 주목하자. 이 헤더파일은 Foundation.h 가 NSString.h 와 NSObject.h 같이 필요한 헤더파일들을 임포트하는 방식과 유사하게, 다른 UIKit 헤더파일을 임포트한다. 만일 이 파일의 내용을 확인하고 싶다면 탐색을 좀 해야 한다. 이 글을 작성할 즈음, 내 시스템 에서는 다음 경로에 파일들이 담겨 있었다.


/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.1.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIKit.h.


iPhone_lAppDelegate 클래스는 이제 인스턴스 변수를 두 개 갖는다. 첫째 변수는 UIWindow 객체인 window 다. 이 인스턴스 변수는 프로젝트를 생성할 때 자동으로 생성되었고, 아이폰의 메인 윈도를 참조한다. 추가한 다른 인스턴스 변수는 UILable 클래스인 display다. 이 변수는 레이블에 연결된 아웃렛 변수다. 이 변수의 텍스트 필드를 설정하면, 윈도에 있는 레이블에 해당하는 텍스트가 업데이트된다. UILabel 클래스에 정의된 다른 메서드를 쓰면 레이블의 색상, 줄수, 폰트 크기와 같은 속성을 설정하거나 받아올 수 있다.

여기서 설명하지 않은 아이폰 프로그래밍에 대해 더 배울수록 인터페이스에 있는 다른 클래스들을 사용하고 싶을 것이다. 이런 클래스들의 이름(UITextField, UIFont, UIView, UITableView, UllmageView, Ullmage, UIButton)은 어떤 목적으로 사용하는지를 알려 주는 실마리가 된다.

window 와 display 인스턴스 변수는 둘 다 아웃렛이고 두 변수에 대한 프로퍼티 선언에서 IBOutlet 구분자가 사용되었음을 알 수 있다. 사실 IBOutlet 은 UIKit 헤더파일인 UINibDeclarations.h 에 정의된 대로 아무것도 아니다(말 그대로 전처리기가 소스 파일에서 대치해 없애 버린다). 그러나 인터페이스 빌더가 어떤 변수를 아웃렛으로 사용할 수 있는지 알아낼 때, 헤더파일을 읽어 IBOutlet 을 찾기 때문에 구분자를 사용해 줘야한다.

인터페이스 파일에서, 메서드 click1: 이 sender 는 인수를 하나 받도록 선언된점에 주목하자. click1: 메서드는 호출되면, 인수 sender 에 이벤트에 관련된 정보를 받는다. 예를 들어 여러 버튼을 누를 때, 이를 처리하는 액션 루틴이 하나밖에 없다면, 이 인수를 확인하여 어떤 버튼이 눌렸는지 알아낸다.

click1:은 IBAction 형의 값을 반환하도록 정의되었다(이것은 UINibDeclarations.h 헤더파일에 void 로 정의되어 있다). IBOutlet 과 마찬가지로, 인터페이스 빌더는 헤더파일을 읽을 때 이 구분자를 사용하여 액션으로 쓸 수 있는 메서드를 찾는다.

이제 클래스의 구현 파일에 해당하는 iPhone_1AppDelegate.m 을 수정할 차례다. 여기서 display 변수의 접근자 메서드는 자동 생성하고(window의 접근자 메서드는 이미 자동 생성되어 있다) click1: 메서드에 대한 정의를 추가한다.

구현 파일을 수정하여 프로그램 21.1 처럼 만들자.


프로그램 21.1 iPhone_1AppDelegate.m


#import "iPhone_1AppDelegate.h"

@implementation iPhone_1AppDelegate
@synthesize window, display;

- (void) applicationDidFinishLaunching:(UIApplication *)application {
    // 응용 프로그램 구동 후 사용자화하려면 이곳에 코드를 추가하라.
    [window makeKeyAndVisible];
}

-(IBAction) click1: (id) sender
{
    [display setText: @"1"];
}

- (void) dealloc {
    [window release];
    [super dealloc];
}

@end


applicationDidFinishLaunching: 메서드는 아이폰 런타임 시스템 에 의해 단 한 번 호출된다. 그 이름이 암시하듯, 응용 프로그램이 구등을 마쳤음을 의미한다. 이곳에서 여러분의 인스턴스 변수를 초기화하고, 화면에 무언가를 그리고, 윈도의 내용을 보이게 하여 화면에 표시할 수 있다. 이 마지막 작업은 메서드의 끝에서 makeKeyAndVisible 메시지를 윈도에 보내면 된다.

click1: 메서드는 UILabel 의 setText: 메서드를 사용하여 아웃렛 변수 display 를 스트링 1 로 설정한다. 버튼을 누르면 이 메서드가 호출 되도록 두개를 연결한다. 그러면 아이폰의 윈도에 1 을 표시할 수 있다. 연결을 만들려면 인터페이스 빌더를 사용한 방법을 배워야 한다. 그 전에 프로그램을 빌드하여 컴파일러 경고나 오류 메시지를 제거하자.


인터페이스 디자인하기

그림 21.4 와 Xcode 의 메인 윈도에서 MainWindow.xib 파일을 보자. xib 파일은 프로그램에서 사용자 인터페이스에 대한 정보를 모두 담는다. 이 정보에는 윈도, 버튼, 레이블, 탭, 바, 텍스트 필드 등이 다들어간다. 물론, 아직 사용자 인터페이스를 만들지 않았다! 바로 다음 단계에서 사용자 인터페이스를 만들 것이다.

MainWindow.xib 파일을 더블 클릭하자. 그러면 인터페이스 빌더라는 프로그램이 구동될 것이다. 여러분의 Resources 폴더에서 xib 파일에 접근할 수도 있다.

인터페이스 빌더가 시작하면 그림 21.6, 그림 21.7, 그림 21.8 처럼 화면에 여러 윈도가 뜰 것이다. 실제로 뜬 윈도는 그림과 조금 다를수도 있다.

라이브러리 윈도는 여러분의 인터페이스에서 사용할 수 있는 컨트롤 팔레트를 제공한다. 그림 21.6 에서 나온 모습은 이 윈도의 디스플레이 모드 가운데 하나다.

MainWindow.xib 윈도(그림 21.7)는 곧 다룰, 응용프로그램 코드와 인터페이스간에 연결을 설정하는 컨트롤 창이다.

그림 21.6 인터페이스 빌더 라이브러리 윈도
그림 21.7 인터페이스 빌더 MainWindow.xib
그림 21.8 인터페이스 빌더 아이폰 윈도


이 가운데 Window 창은 아이폰 메인 윈도의 레이아웃을 보여 준다. 아이폰의 윈도에는 아직 아무것도 디자인해 넣지 않았기 때문에, 그림 21.8 처럼 그저 빈 상태로 나타난다.

맨 먼저 할 일은 아이폰의 윈도를 검정색으로 설정하는 것이다. 이를 위해서 Window 라는 윈도의 내부를 클릭한다. 그리고 Tools 메뉴에서 Inspector 를 선택하면 그림 21.9 와 같이 인스펙터 창이 뜰 것이다.

그림 21.9 인터페이스 빌더 인스펙터 창


인스펙터 창이 그림 21.9 처럼 Window Attribute 라는 이름으로 되어 있는지 확인하자. 만일 아니라면, 위의 탭 바에서 가장 왼쪽 랩을 클릭하여 올바른 윈도가 표시되도록 조정한다.

윈도의 View 부분을 보면, Background 라는 속성을 볼 수 있다. Background 옆의 흰색으로 칠해진 사각형의 내부를 더블클릭하면 컬러 선택기가 뜰 것이다. 선택기에서 검정색을 택하면, 인스펙터 내 Background 속성 옆에 있는 사각형 색이 검정으로 바뀐다(그림 21.10 을 보라).

아이폰의 디스플레이 윈도를 나타내는 Window 라는 윈도를 살펴보면, 그림 21.11 과 같이 검정색으로 바뀌었을 것이다.

이제 Colors 윈도를 닫아도 된다.

그림 21.10 윈도의 배경색 바꾸기
그림 21.11 인터페이스 윈도가 검정으로 바뀌었다.


라이브러리 윈도에서 객체를 클릭하고 여러분의 아이폰 윈도로 드래그하여 넣으면 아이폰 인터페이스에 새 객체를 생성할 수 있다. 지금은 Label 을 클릭하고 드래그하자. 그림 21.12 처럼 레이블이 윈도 중앙 그리고 위쪽에 가까이 있을때 마우스의 버튼을 놓자.

그림 21.12 레이블 추가하기


윈도 안에서 레이블을 움직이면 파란색 가이드라인이 나타날 것이다. 때로는, 이 라인이 나타나, 윈도에 이미 자리를 잡은 다른 객체에 맞게 객체를 배치하도록 도와준다. 또는 이 라인을 보면서 애플의 인터페이스 가이드라인에 따라, 객체가 다른 객체나 윈도 경계에서 충분히 거리를 두도록 배치한다.

원한다면 언제든 레이블을 드래그하여 윈도내 다른 위치로 옮길 수 있다.

이제 이 레이블의 속성을 설정해 주자. 윈도에서 방금 만든 레이블을 클릭하여 선택한다. 인스펙터 창이 자동으로 바뀌어 윈도에서 현재 선택된 객체에 대한 정보를 표시하는지 확인하자. 이 레이블에 기본적으로 아무 텍스트도 표시하지 않으려면 Text 의 값을 비어있는 스트링으로 설정하면 된다(이 말은, 인스펙터 의 창에서 이 텍스트필드 에 있는 Label 스트링을 삭제한다는 의미다).

Layout 속성에서 Right-justfied(우측 정렬)을 선택한다. 마지막으로 윈도 배경색을 검정으로 변경했던 것처럼 레이블 배경색을 파란색이나 원하는 다른 색으로 변경해 준다. 여러분의 인스펙터 창은 그림 21.13 과 유사하게 되었을 것이다.

이제 레이블의 크기를 변경해 보자. Window 로 돌아가 레이블의 구석과 측면을 잡고 끌어 크기를 바꾼다. 이 레이블 크기를 바꾸고 위치를 조절하여 그림 21.14 와 유사하게 만들자.

드디어 인터페이스에 버튼을 추가할 차례다. 라이브러리 창에서 Round Rect Button 객체를 클릭하고 드래그하여 인터페이스 창에 넣고, 그림 21.15 에서 보이듯이 윈도의 좌측 하단 구석에 배치하자. 버튼 이름은 두 가지 방식으로 바꿀 수 있다. 버튼을 더블 클릭해 텍스트를 입력하거나, 인스펙터 창의 Title 필드를 설정해 주면 된다. 어느 방식을 사용하던지간에 여러분의 윈도가 그림 21.15 처럼 보이도록 하자.

그림 21.13 레이블 속성 변경하기
그림 21.14 레이블의 크기를 조절하고 위치 설정하기
그림 21.15 인터페이스에 버튼 추가하기


이제 display 인스턴스 변수에 연결할 레이블이 생겼으므로 프로그램에서 변수를 설정하면 레이블의 텍스트도 변경될 것이다.

또한 1 이라는 이름의 버튼을 누르면, click1: 메서드가 호출되도록 설정하였다. 이 메서드는 display의 텍스트 필드 값을 1 로 설정한다. 이 변수가 레이블에 연결될 것이기 때문에, 레이블도 업데이트될 것이다. 정리하는 의미로 이 과정을 다시보자.

  1. 사용자가 1 이 라는 이름이 불은 버튼을 누른다.
  2. 이 이벤트로 인해 click1: 메서드가 호출된다.
  3. click1: 메서드는 인스턴스 변수 display 의 텍스트를 1 로 만든다.
  4. UILabel 객체인 display가 아이폰 윈도 안의 레이블에 연결되어 있으므로, 이 레이블도 해당하는 텍스트 값, 즉 1 로 업데이트된다.


이 과정을 밟아 나가려면 그저 연결만 두 개 만들어 주면 된다. 어떻게 하면 되는지 살펴보자.

먼저 버튼을 IBAction 메서드인 click1: 에 연결하자. 컨트롤 키를 누른 채로 버튼을 누르고, 스크린에 생기는 파란선을 mainWindow.xib 윈도안의 응용 프로그램 델리게이트에 드래그하여 연결 을생성한다. 그림 21.16 에 이것이 나타나있다.

델리게이트 육면체에서 마우스를 놓으면 드롭다운 메뉴가 나타난다. 여기서 이 버튼에 연결할 IBAction 메서드를 선택할 수 있다. 우리의 경우 그런 메서드가 click1: 하나 뿐이므로 드롭다운 메뉴에 그것만 나타난다. 그림 21.17 처럼 그 메서드를 선택하여 연결을 만들어 주자;

이제 display 변수를 레이블에 연결하자. 버튼을 누르면 응용 프로그램에 있는 메서드가 실행되지만(이것은 액션의 흐름이 인터페이스에서 응용 프로그램 델리게이트로 흐른다는 이야기다), 응용 프로그램 안의 인스턴스 변수값을 설정하면, 아이폰 윈도에 있는 레이블이 업데이트된다(즉, 액션의 흐름이 응용 프로그램 델리게이트에서 인터페이스로 흐른다). 이런 이유로, 컨트롤키를 누른채로 응용프로그램 델리게이트 아이콘을 누르고, 이후 나타니는 파란 선을 Window 에 있는 레이블로 드래그한다. 그림 21.18 은 이것을 보여 준다.

그림 21.16 버튼에 액션 추가하기
그림 21.17 이벤트를 메서드에 연결하기


이제 마우스 버튼을 놓으면, 우리는 컨트롤에 해당하는 클래스(UILabel)의 IBOutlet 변수의 목록을 받는다. 그림 21.19 에 나타난 것처럼 우리 프로그램에서 그런 변수는 딱 하나 display 뿐이다. 이 변수를 선택하고 연결을 만들어 주자.

그림 21.18 아웃렛 변수 연결하기
그림 21.19 연결 완료하기
그림 21.20 실행된 분수 계산기


자, 이것으로 끝이다! 인터페이스 빌더의 메뉴 바에서 File -> Save 를 선택하고 Xcode 에서 Build and Go 를 해주자(인터페이스 빌더에서도 해줄 수 있다)

모든 게 잘 되었다면, 프로그램은 성공적으로 빌드되어 실행이 시작된다. 실행이 시작될 때, 프로그램은 여러분의 컴퓨터에 나타나는 아이폰 시뮬레이터에 로드될 것이다. 시뮬레이터 창은 그림 21.1 처럼 나타날것이다. 시뮬레이터에서는 버튼을 누르는 대신에 그저 마우스로 클릭하면 된다. 그렇게 하면, 앞서 정리했던 과정을 밟고 연결까지 마친 결과로, 그림 21.2 와 같이 디스플레이의 맨 위 레이블에 스트링 1 이 표시될 것이다.


아이폰 분수 계산기

다음 예제는 조금 더 복잡하지만 앞서 예제에서 배운 개념들이 동일하게 적용된다. 이 예제를 만들면서 모든 단계를 보여 주지 않고, 각 단계를 요약하고 디자인 방법에 대한 개요만 살펴볼 것이다. 물론 코드는 모두 보여줄 것이다.

먼저 이 응용 프로그램이 어떻게 동작하는지 보자. 그림 21.20 은 이 응용 프로그램이 시뮬레이터에서 실행된 직후의 모습이다.

계산기 프로그램에서는 첫 입력으로 분자가 입력되고, Over 라는 키를 누른 후 입력하면 분모가 입력된다. 따라서 분모 2/5 를 입력하려면 먼저 2 를 누르고 Over 를 누른다음 5 를 눌러야 한다. 이 계산기는 다른 계산기와 달리 화면에 분수를 보여 준다. 즉, 2/5 는 2/5 로 표시될 것이다.

분수를 하나 입력한 뒤에 각각 적절히 +,-,*,/ 로 이름불은 키를 눌러 덧셈, 뺄셈, 곱셈, 나눗셈 연산을 입력한다.

두 번째 분수를 입력한 뒤에, 일반 계산기와 같이 = 키를 눌러 연산을 완료한다.


objc2_notice_01
이 계산기는 분수 두 개 사이에서 단일 연산만 하도록 디자인되었다. 이 제한을 없애는 일은 연습문제로 남겨 두었다.


화면은 키가 입력되면서 계속 업데이트된다. 그림 21.21 은 분수 4/6 가 입력되고 곱셈 키가 입력된 후의 화면이다.

그림 21.22 에는 4/6 과 2/8 를 곱한 결과가 나온다. 결과로 1/6 이 나왔는데, 이로써 결과값이 약분 되었음을 확인할 수 있다.


Fraction_Calculator 프로젝트 새로 시작하기

첫 번째 아이폰 프로그램은 윈도 기반 프로젝트 템플릿에서 시작했다. 여기서 (최소한의)UI 작업은 애플리케이션 컨트롤러 (AppDelegate 클래스)에서 직접 수행했다. 그러나 UI가 풍성한 응용 프로그램을 개발할 때는 이런 방법을 추천하지 않는다. 보통 AppDelegate 클래스는 응용 프로그램이 구등을 마쳤다거나 비활성화 되려는 시기처럼, 응용 프로그램의 상태와 관련된 작업만 처리해 준다.

이제 (UIViewController 클래스로 구현된) 뷰 컨트롤러에서 UI 와 관련된 액션들을 수행해야 한다. 이런 액션은 텍스트를 표시하거나, 버튼이 눌려서 이에 대응하거나, 아이폰 스크린에 완전히 새로운 뷰를 띄우는 등의 작업이다.

그림 21.21 연산 키 입력하기


이 두 번째 프로그램 예제에서 새 프로젝트를 생성하여 시작할 것이다. 이번에는 NewProject 창에서 View-Based Application 을 선택하자. 새 프로젝트는 이름을 Fraction_ Calculator 라고 짓는다.

프로젝트를 만들면 이번에는 두 클래스의 템플릿이 정의되어 있다는걸 알게 된다. Fraction_CalculatorAppDelegate.h 와 Fraction_CalculatorAppDelegate.m 은 프로젝트의 애플리케이션 컨트롤러 클래스를 정의하고, Fraction_CalculatorViewController.h 와 Fraction_ CalculatorViewController.m 은 뷰 컨트롤러 클래스를 정의한다. 이미 언급한대로, 두번째 클래스에서 모든 작업을 수행할 것이다.

먼저, 애플리케이션 컨트롤러 클래스로 시작한다. 이 클래스는 인스턴스 변수를 두 개 담고 있는데 하나는 아이폰의 윈도를 가리키고, 다른 하나는 뷰 컨트롤러를 가리킨다. 이것들은 모두 Xcode 에서 설정된다. 사실 애플리케이션 컨트롤러의 .h 나 .m 파일에는 수정을 가할 필요가 없다.

그림 21.22 두 분수의 곱셈 결과


프로그램 21.2 는 Fraction_CalculatorAppDelegate 인터페이스 파일이다.


프로그램 21.2 Fraction_CalculatorAppDelegate.h 인터페이스 파일


#import <UIKit/UIKit.h>

@class Fraction_CalculatorViewController;

@interface Fraction_CalculatorAppDelegate : NSObject <UIApplicationDelegate>
{
    IBOutlet UIWindow *window;
    IBOutlet Fraction_CalculatorViewController *viewController;
}

@property (nonatomic, retain) UIWindow *window;
@property (nonatomic, retain) Fraction_CalculatorViewController *viewControoler;

@end


여기서 UIWindow 인스턴스 변수인 windows 는 첫 번째 예제에서와 동일한 목적으로 사용한다. 즉, 아이폰의 윈도를 나타내는 것이다. Fraction_CalculatorViewController 인스턴스 변수는 사용자와 일어나는 모든 상호작용을 처리하고 화면에 이를 표시할 뷰 컨트롤러다. 이 클래스를 구현한 파일에 이 작업에 관련된 모든것을 넣을것이다.

프로그램 21.2 는 애플리케이션 컨트롤러 클래스의 구현 파일이다. 이미 언급했듯이 프로그램 21.1 에서 한 작업들을 이 파일에는 하지 않을 것이다. 모든 작업은 뷰 컨트롤러에게 위임한다. 따라서 이 파일은 프로젝트가 생성될 때 Xcode 가 만들어준 그대로 둘 것이다.


프로그램 21.2 Fraction_Calculator_AppDelegate.m 구현 파일


#import "Fraction_CalculatorAppDelegate.h"
#import "Fraction_CalculatorViewController.h"

@implementation Fraction_CalculatorAppDelegate

@synthesize window;
@synthesize viewController;

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    // 응용 프로그램 실행 후 사용자화하려면 이곳에 코드를 추가한다.
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
}

- (void)dealloc {
    [viewController release];
    [super dealloc];
}

@end

뷰 컨트롤러 정의하기

이제 뷰 컨트롤러 클래스인 Fraction_CalculatorViewController 를 위한 코드를 작성할 때가 되었다. 인터페이스 파일부터 시작해야 한다. 프로그램 21.2 에 그 코드가 나와있다.


프로그램 21.2 Fraction_CalculatorViewController.h 인터페이스 파일


#import <UIKit/UIKit.h>
#import "Calculator.h"

@interface Fraction_CalculatorViewController : UIViewController {
    UILabel *display;
    char op;
    int currentNumber;
    NSMutableString *displayString;
    BOOL firstOperand, isNumerator;
    Calculator *myCalculator;
}

@property (nonatomic, retain) IBOutlet UILabel *display;
@property (nonatomic, retain) NSMutableString *displayString;

-(void) processDigit: (int) digit;
-(void) processOp: (char) theOp;
-(void) storeFracPart;

// 숫자 키

-(IBAction) clickDigit: (id) sender;

// 산술 연산 키

-(IBAction) clickPlus: (id) sender;
-(IBAction) clickMinus: (id) sender;
-(IBAction) clickMultiply: (id) sender;
-(IBAction) clickDivide: (id) sender;

// 기타 키

-(IBAction) clickOver: (id) sender;
-(IBAction) clickEquals: (id) sender;
-(IBAction) clickClear: (id) sender;

@end


클래스에는 분수를 만드는 변수들(currentNumber, firstOperand, isNumerator)과 표시해 주는 스트링 변수(displayString)가 있다. 그리고 두 분수 사이에서 실제 계산을 수행할 calcurator 객체 (myCalculator)도 있다. 숫자 키 0~9 중 어느 키든 눌렀을 때 이를 처리할 단일 메서드 clickDigit: 를 정의한다. 또한 수행될 연산을 저장할 메서드(clickPlus: , clickMinus:, clickMultiply:, clickDivide:)와 = 키가 눌렸을 때 실제 연산을 수행할 메서드(clickEquals:), 현재 연산을 제거할 메서드(clickClear:) 그리고 Over 키를 눌렀을 때, 분자와 분모를 구분해 주는 메서드(clickOver:)도 정의한다. 몇몇 메서드(processDigit:, processOp:, storeFracPrat:)는 이미 언급한 메서드를 돕는 용도로 정의된다.

프로그램 21.2 는 이 컨트롤러 클래스를 구현한 파일이다.


프로그램 21.2 Fraction_CalculatorViewController.m 구현 파일


#import "Fraction_CalculatorViewController.h"
@implementation Fraction_CalculatorViewController

@synthesize displayString, display;

- (void)viewDidLoad {
    // 응용 프로그램 실행 후 사용자화하려면 여기에 코드를 추가한다.

    firstOperand = YES;
    isNumerator = YES;
    self.displayString = [NSMutableString stringWithCapacity: 40];
    myCalculator = [[Calculator alloc] init];
}

-(void) processDigit: (int) digit
{
    currentNumber = currentNumber * 10 + digit;

    [displayString appendString: [NSString stringWithFormat: @"%i", digit]];
    [display setText: displayString];
{

- (IBAction) clickDigit:(id)sender
{
    int digit = [sender tag];

    [self processDigit:digit];
}

-(void) processOp: (char) theOp
{
    NSString *opStr;

    op = theOp;

    switch (theOp) {
    case '+':
        opStr = @"+ ";
        break;
    case '-':
        opStr = @"? ";
        break;
    case '*':
        opStr = @"x";
        break;
    case '/':
        opStr = @"/ ";
        break;
    }

    [self storeFracPart];
    firstOperand = NO;
    isNumerator = YES;

    [displayString appendString: opStr];
    [display setText: displayString];
}

-(void) storeFracPart
{
    if (firstOperand) {
        if (isNumerator) {
            myCalculator.operand1.numerator = currentNumber;
            myCalculator.operand1.denominator = 1; // 예. 3 * 4/5 =
        }
        else
            myCalculator.operand1.denominator = currentNumber;
        {
    else if (isNumerator) {
        myCalculator.operand2.numerator = currentNumber;
        myCalculator.operand2.denominator = 1; // 예. 3/2 * 4 =
    }
    else {
        myCalculator.operand2.denominator = currentNumber;
        firstOperand = YES;
    }

    currentNumber = 0;
}

-(IBAction) clickOver: (id) sneder
{
    [self storeFracPart];
    isNumerator = NO;
    [displayString appendString: @"/"];
    [display setText: displayString];
}

// 산술 연산 키

-(IBAction) clickPlus: (id) sender
{
    [self processOp: '+'];
}

-(IBAction) clickMinus: (id) sender
{
    [self processOp: '-'];
}

-(IBAction) clickMultiply: (id) sender
{
    [self processOp: '*'];
}

-(IBAction) clickDivide: (id) sender
{
    [self processOp: '/'];
}

// 기타 키

-(IBAction) clickEquals: (id) sender
{
    [self storeFracPart];
    [myCalculator performOperation: op];
    [displayString appendString:@"= "];
    [displayString appendString: [myCalculator.accumulator convertToString]];
    [display setText: displayString];

    currentNumber = 0;
    isNumerator = YES;
    firstOperand = YES;
    [displayString setString: @""];
}

-(IBACTION) clickClear: (id) sender
{
    isNumerator = YES;
    firstOperand = YES;
    currentNumber = 0;
    [myCalculator clear];

    [displayString setString: @""];
    [display setText: displayString];
}

- (void)dealloc {
    [myCalculator release];
    [super dealloc];
}

@end


계산기의 윈도는 여전히 이전 응용 프로그램처럼 레이블 하나만 포함할 뿐이다. 이 윈도를 계속 display 라고 부르겠다. 사용자가 숫자를 하나썩 입력하면 그에 따라 숫자를 만들어야 한다. 변수 current_Number 에는 현재 진행 중인 숫자가 들어 있고, BOOL 변수 firstOperand 는 입력 중인 피연산자가 첫 번째인지 혹은 두 번째인지에 대한 정보를 담았고, isNumerator 는 사용자가 현재 피연산자의 분자를 입력하는지 아니면 분모를 입력하는지에 대한 정보를 담았다.

계산기의 숫자 버튼을 누르면 clickDigit: 메서드에 식별할 수 있는 정보가 건네진다. 그를 통해 어느 버튼을 눌렀는지 구분할 수 있다. 이를 위해 (인터페이스 빌더의 인스펙터에서)버튼의 속성인 tag 를 각 숫자버튼에 대한 유일한 값으로 설정한다. 여기서는, 해당 숫자로 각각 태그를 설정하면 좋을 것이다. 즉, 0 이 불은 버튼의 태그는 0 이 되고, 이름이 1 인 버튼의 태그는 1 로 설정되는 식이다. clickDigit: 에 넘겨지는 sender 매개변수에 tag 메시지를 보내 버튼의 태그 값을 가져올 수 있다. 다음과 같이 clickDigit: 메서드를 써서 이 작업을 수행한다.

- (IBAction) clickDigit:(id)sender
{
    int digit = [sender tag];

    [self processDigit:digit];
}


프로그램 21.2 에는 첫 번째 프로그램보다 버튼이 더 많다. 뷰 컨트롤러 구현 파일에서 복잡한 것들은 대부분 분수를 만들고 표시하는 일과 관련 있다. 앞서 언급한대로, 숫자버튼 0~9 를 누르면 clickDigit: 액션 메서드가 실행된다. 이 메서드는 processDigit: 메서드를 호출하여 지금 currentNumber 변수에 들어 있는 숫자 뒤에 입력받은 숫자를 붙여 넣는다. processDigit: 메서드는 숫자를 붙여 넣을뿐 아니라 displayString 변수에 저장되는 현재 디스플레이 스트링에도 숫자를 더한다. 그리고 텍스트 레이블(display)을 업데이트한다.

-(void) processDigit: (int) digit
{
    currentNumber = currentNumber * 10 + digit;

    [displayString appendString: [NSString stringWithFormat: @"%i", digit]];
    [display setText: displayString];
}


= 키를 누르면 clickEquals: 메서드가 호출되어 연산이 수행된다. 계산기는 두 분수의 연산을 수행하고 결과를 누산기(accumulator) 에 저장한다. 이 누산기는 clickEquals: 메서드에서 그 결과를 가져와서 display 에 더한다.


Fraction 클래스

Fraction 클래스는 앞 예제에서 봤을 때와 크게 달라진 것이 없다. 여기에다 convertToString 메서드가 새로 더해져 분수를 스트링으로 표현할 수 있다. 프로그램 21.2 는 Fraction 인터페이스 파일이고, 구현 파일이 뒤따른다.


프로그램 21.2 Fraction.h 인터페이스 파일


#import <UIKit/UIKit.h>

@interface Fraction : NSObject {
    int numerator;
    int denominator;
}

@property int numerator, denominator;

-(void) print;
-(void) setTo: (int) n over: (int) d;
-(Fraction *) add: (Fraction *) f;
-(Fraction *) subtract: (Fraction *) f;
-(Fraction *) multiply: (Fraction *) f;
-(Fraction *) divide: (Fraction *) f;
-(void) reduce;
-(double) convertToNum;
-(NSString *) convertToString;

@end



프로그램 21.2 Fraction.m 구현 파일


#import "Fraction.h"

@implementation Fraction

@synthesize numerator, denominator;

-(void) setTo: (int) n over: (int) d
{
    numerator = n;
    denominator = d;
}

-(void) print
{
    NSLog (@"%i/%i", numerator, denominator);
}

-(double) convertToNum
{
    if (denominator != 0)
        return (double) numerator / denominator;
    else
        return 1.0;
}

-(NSString *) convertToString;
{
    if (numerator == denominator)
        if (numerator == 0)
            return @"0";
        else
            return @"1";
    else if (denominator == 1)
        return [NSString stringWithFormat: @"%i", numerator];
    else
    return [NSString stringWithFormat: @"%i/%i",
        numerator, denominator];
}

// 수신자에 분수를 더한다.

-(Fraction *) add: (Fraction *) f
{
    // 두 개의 분수를 더하려면
    // a/b + c/d = ((a*d) + (b*c)) / (b * d)

    // 덧셈 결과를 result에 저장한다.
    Fraction *result = [[Fraction alloc] init];
    int resultNum, resultDenom;
    resultNum = numerator * f.denominator + denominator * f.numerator;
    resultDenom = denominator * f.denominator;

    [result setTo: resultNum over: resultDenom];
    [result reduce];

    return [result autorelease];
}

-(Fraction *) subtract: (Fraction *) f
{
    // 두 개의 분수를 빼려면
    // a/b - c/d = ((a*d) - (b*c)) / (b * d)

    Fraction *result = [[Fraction alloc] init];
    int resultNum, resultDenom;
    resultNum = numerator * f.denominator - denominator * f.numerator;
    resultDenom = denominator * f.denominator;

    [result setTo: resultNum over: resultDenom];
    [result reduce];
    return [result autorelease];
}

-(Fraction *) multiply: (Fraction *) f
{
    Fraction *result = [[Fractino alloc] init];

    [result setTo: numerator * f.numerator over: denominator
                * f.denominator];
    [result reduce];

    return [result autorelease];
}

-(Fraction *) divide: (Fraction *) f
{
    Fraction *result = [[Fraction alloc] init];

    [result setTo: numerator * f.denominator over: denominator * f.numerator];
    [result reduce];

    return [result autorelease];
}

- (void) reduce
{
    int u = numerator;
    int v = denominator;
    int temp;

    if (u == 0)
        return ;
    else if (u <0)
        u = -u;

    while (v != 0) {
        temp = u % v;
        u = v;
        v = temp;
    }

    numerator /= u;
    denominator /= u;
}

@end


convertToString: 메서드는 분수의 분자와 분모를 확인하여 좀더 보기 좋게 결과를 만들어낸다. 만일 분자와 분모가 동일하면(그러나 0의 경우는 제외하고), @"1" 을 반환한다. 만일 분자가 0 이면 스트링 @"0" 이 반환된다. 분모가 1 이면 정수 이므로 분모를 표시할 필요가 없다.

convertToString: 안에서 사용한 stringWithFormat: 메서드는 주어진 포맷 스트링(NSLog과 동일)과 쉼표로 분리한 인수 리스트로 스트링을 만들어 반환한다. NSLog 함수에 인수를 건넬 때 했던 것처럼 인수를 원하는 수 만큼 쉼표로 구분해서 이 메서드에 넘긴다.


분수를 다루는 Calculator 클래스

이제 Calculator 클래스를 살펴볼 시간이다. 책 앞부분에서 개발했던 Calculator 클래스와 거의 유사하다. 그러나 지금은, 우리의 계산기가 분수를 어떻게 다뤄야 할지 알고 있어야 한다. 새 Calculator 클래스 인터페이스 파일과 구현 파일을 보자.


프로그램 21.2 Calculator.h 인터페이스 파일


#import <UIKit/UIKit.h>
#import "Fraction.h"

@interface Calculator : NSObject {
    Fraction *operand1;
    Fraction *operand2;
    Fraction *accumulator;
}

@property (retain, nonatomic) Fraction *operand1, *operand2, *accumulator;

-(Fraction *) performOperation: (char) op;
-(void) clear;

@end



프로그램 21.2 Calculator.m 구현 파일


#import "Calculator.h"

@implementation Calculator
-(id) init
{
    self = [super init];
    operand1 = [[Fraction alloc] init];
    operand2 = [[Fraction alloc] init];
    accumulator = [[Fraction alloc] init];

    return self;
}

-(void) clear
{
    if (accumulator) {
        accumulator.numerator = 0;
        accumulator.denominator = 0;
    }
}

-(Fraction *) performOperation: (char) op
{
    Fraction *result;

    switch (op) {
    case '+':
        result = [operand1 add: operand2];
        break;
    case '-':
        result = [operand1 subtract: operand2];
        break;
    case '*':
        result [operand1 multiply: operand2];
        break;
    case '/':
        result = [operand1 divide: operand2];
        break;
    }

    accumulator.numerator = result.numerator;
    accumulator.denominator = result.denominator;

    return accumulator;
}

-(void) dealloc
{
    [operand1 release];
    [operand2 release];
    [accumulator release];
    [super dealloc];
}

@end


UI 디자인하기

프로젝트의 Resources 폴더에는 xib 파일이 두 개 있다. 하나는 MainWindow.xib 이고 다른 하나는 Fraction_CalculatorViewController.xib 이다. 앞 파일은 전혀 건드릴 필요가 없으므로, 뒤 파일을 더블 클릭하여 열자. 인터페이스 빌더가 시작되면 'View' 라는 이름이 붙은 아이콘을 Fraction_CalculatorViewController.xib 라는 윈도에서 찾을수 있다. 그림 21.23 은 이것을 보여 준다.

만일 View 윈도가 열려 있지 않다면 아이콘을 더블 클릭해서 열자. 이 View 윈도 안에서 계산기 UI 를 디자인할 것이다. 각 숫자 버튼과 clickDigit: 버튼을 연결해 주자. 각 버튼을 컨트롤 키를 누른 채 클릭하고 Fraction_CalculatorViewController.xib 윈도 안에 있는 File's Owner 아이콘에 드래그한다. 그 다음 이벤트 드롭다운에서 clickDigit: 를 선택해 주면 된다. 또, 버튼마다 인스펙터 창의 태그 값을, 버튼의 타이틀에 해당하는 숫자로 지정해 주자. 숫자 버튼의 타이틀이 1 이라면, 태그 값도 0 으로 설정해주고, 숫자버튼의 타이틀이 1 이라면 태그값도 1 로 설정해 준다.

View 윈도에 있는 남은 버튼도 드래그하여 해당하는 연결을 만들자. 잊지 말고 계산기의 화면에 레이블을 넣고 File's Owner에서 그 레이블로 컨트롤 키를 누른채 클릭해 드래그한다. 아웃렛 드롭다운이 나타나면 display를 선택한다.

이게 끝이다! 인터페이스의 디자인이 끝났고, 분수 계산기 프로그램은 작동할 준비가 되었다!

그림 21.23 Fraction_CalculatorViewController.xib 윈도


요약

그림 21.24 는 분수 계산기 프로젝트에 관련된 파일을 모두 볼 수 있는 Xcode 프로젝트 윈도의 모습이다.

그림 21.24 분수 계산기 프로젝트 파일


아이폰 분수 계산기 프로그램을 만들면서 여러분이 따라온 각 단계를 요약했다.

  1. 뷰 기반 응용 프로그램을 새로 만들었다.
  2. UI 코드를 Fraction_CalculatorViewController. h와 .m 파일에 입력한다.
  3. Fraction 클래스와 Calculator 클래스를 프로젝트에 추가하였다.
  4. 인터페이스 빌더 에서 Fraction_CalculatorViewController.xib 파일을 열어 UI 를 만들었다.
  5. View의 윈도의 배경을 검정색으로 만들었다.
  6. 레이블과 버튼을 만들어 View 윈도내에 배치하였다.
  7. File's Owner 를 View 윈도에 만든 레이블로 컨트롤 키를 누른 채 드래그하여 'display'로 설정하였다.
  8. View 안에 있는 각 버튼을 File's Onwer 로 컨트롤 키를 누른 채 클릭, 드래그해 적절한 액션 메서드로 연결하였다. 각 숫자 버튼에 대해서는 clickDigit: 메서드를 선택했다. 또한, 각 숫자 버튼의 tag 버튼 속성을 각 버튼에 해당되는 숫자(0~9)로 지정하여 어느 버튼을 눌렀는지를 clickDigit: 메서드가 식별하도록 만들었다.


애플리케이션 컨트롤러에서 처리할 때보다 좀더 작업해야 했지만, 뷰 컨트롤러를 사용하는 방법은 꽤 배울 만한 가치가 있다. 응용 프로그램에서 애니메이션, 화면 돌리기, 내비게이션 컨트롤러 사용하기, 탭 인터페이스 구축하기 같은 복잡한 작업을 하려면 뷰 컨트롤러를 사용해야 한다.

아이폰 응용 프로그램을 개발하는 과정을 짧게나마 소개했는데, 이것이 여러분 자신의 아이폰 응용 프로그램을 개발하는데 좋은 시작점이 되길 바란다. 이미 말했지만 UIKit 에는 많은 기능이 있으며, 여러분이 탐험할 부분이 많이 남아 있다.

우리가 만든 분수 계산기 프로그램에는 제약이 몇 가지 있다. 다음 연습문제에서 이 제약들을 보완해 보자.


연습문제

1. 분수 계산기에 Convert 버튼을 추가하라. 이 버튼을 누르면, Fraction 클래스의 convertToNum 메서드가 호출되어 분수 결과를 숫자로 표현한다. 결과를 스트링으로 변환하여 계산기의 화면에 표시하자.


2. 분수 계산기를 수정해서 분자가 입력되기 전에 - 키를 누르면 음의 분수를 입력할수 있도록 만들어라.


3. 첫 번째 혹은 두 번째 항의 분모에 0 이 입력되면, 분수 계산기의 디스플레이에 Error 스트링을 표시하자.


4. 분수 계산기에서 계산이 연속해서 이뤄지도록 수정하자. 예를 들어, 다음 연산을 입력할 수 있도록만든다.

1/5 + 2/7 - 3/8 =


5. 응용 프로그램에 아이콘을 추가하여 아이폰의 홈 스크린에 나타나게 만들 수 있다. 아이콘을 표시하려면 그림 21.25 에 나오듯이 프로그램의 Resources 폴더에 아이콘으로 쓸 이미지(.png 파일)를 추가하고, 정보 프로퍼티 리스트(Resources 폴더 안의 Info.plist)에서 'Icon File' 키의 값을 이 이미지 파일로 설정해주면 된다.


인터넷에서 적절한 계산기 이미지를 찾아, 분수 계산기가 이 이미지를 응용 프로그램 아이콘으로 사용하도록 만들자.

그림 21.25 인터페이스에 버튼 추가하기


Notes