최초 작성일 : 2010/08/25 00:17
이번 회 부터 본격적인 소스 분석에 들어가보도록 하겠습니다.
그 전에 먼저 간략하게나마(사실은 설계랄 것이 거의 없는 작업이어서 간략하게 밖에는
설명을 못드립니다…^^;;;) 설계 과정을 보도록 하겠습니다.
1. 설계
우선 기능 목록을 뽑았습니다.
1. 아이를 등록하는 기능
2. 달력 기능
3. 기념일을 등록하는 기능
4. 이벤트를 등록하는 기능
5. 일기를 작성하는 기능
6. 예방접종 안내 및 접종 여부를 선택하는 기능
7. 표준 발육 상태와의 비교를 보여주는 기능
8. 아이와 관련된 이벤트(100일, 돌, 생일 등)를 자동 등록하는 기능
9. 사용자 설정 기능
이 중 시간에 쫓기다보니 육아일기를 특징짓는 6, 7, 8번과
필수적인 기능이라고 할 수 없는 9번은 개발 우선 순위에서 뒤로 밀리고 말았습니다.
기념일 등록같은 경우 원래는 9번의 사용자 설정 탭을 따로 두고 사용자 설정을 통해 등록을
시킬 수 있도록 하려 했으나 설정 내용이 워낙 빈약해서 차라리 설정을 없애고 달력쪽에
기념일을 등록 시킬 수 있도록 수정하였습니다.
대략 이런 설계는 다음 사진 4장으로 압축됩니다.
앞서 말씀드린대로 사실상 설계라고는 이 사진 4장에 있는 노트 뿐입니다…^^;;;
2. 프로젝트 생성
초보자는 무조건 예제로부터 시작을 하게 되죠
저 역시 다르지 않습니다.
처음 프로젝트를 생성한 것은 인터넷 서핑중 발견한 뷰 전환 소스를 바탕으로
하였습니다. 이 소스는 하단에 툴바를 사용하고 툴바에 있는 버튼을 터치하는 경우
두개의 뷰가 동전의 양면처럼 뒤집히는 애니메이션 효과를 보여주며 전환하는 소스였습니다.
따라서 프로젝트 생성시에도 가장 단순하게 View-Based-Application을 선택하여 생성하여서
사실상 별다른 코딩이 없는 상태였습니다. 프로젝트 생성은 기본적인 내용이므로 생략을 합니다.
하지만 중요한 것은 이게 아니고…
3. 메인 화면의 구성
일단 5개의 메인 기능을 결정을 하였으니 화면 구성을 생각해야 했습니다.
전체적인 화면 구조는 최종 결과물과 동일하게 상단에는 네비게이션바를 통해서
각각의 기능 내에서의 네비게이션을 담당하게 하고 각각의 기능들은 하단의
탭바를 통해 전환하도록 구상을 하였습니다.
이 때 2가지 난관에 부딪치게 되었는데
하나는 IB에 대한 무지로 인해 IB를 제대로 사용할 수 없었다는 점과
첫번째 이유로 해서 네비게이션 바와 탭바를 동시에 가지는 화면 구성을 구현하는데
시행착오를 거쳐야 했다는 점입니다.
3.1. 인터페이스 빌더 팁
우선 IB에 대해 기본적으로 몰랐던 점은 xib 창의 좌상단에 있는 View Mode를 적절한
상태로 선택하지 못했던 것입니다.
기본적으로는 아이콘 형태로 보여지게 되어있는데 이렇게 되어있을 경우 각 객체들간의
계층 관계 및 View가 어떤 컨트롤러들로 구성되었는지와 같은 세부적인 내용을 확인할
수 없습니다.
즉 View Mode를 두 번 째나 세 번 째의 리스트 형태로 놓아야 아래 보이는 것처럼
화면의 전체적인 구조를 한 눈에 볼 수 있게 됩니다.
위 이미지의 화면을 보면 TabBarController가 가장 상위에 배치되어있고
그 아래 탭바 하나와 5개의 네비게이션 컨트롤러가 배치되어있습니가.
그리고 각각의 네비게이션 컨트롤러 아래는 탭바 아이템과 탭을 선택한 경우
화면에 보여질 ViewController, 그리고 그 ViewController의 뷰에 보여질
네비게이션 바가 배치됩니다. 마지막으로 각각의 ViewController 아래에는
네비게이션 아이템이 배치되어 해당 뷰로부터 네비게이션 바에 사용되는
네비게이션 아이템에 접근할 수 있도록 되어있습니다.
IB를 이용한 가장 기본적인 형태의 네비게이션 바와 탭바를 동시에 사용할 수 있는
화면 구성입니다.
※ 참고로 각각의 오브젝트를 드래그앤 드롭하여 계층의 위치나 레이아웃에서의 상하
위치를 변경할 수 있습니다.
3.2. 시행착오
3.1의 내용을 몰랐기 때문에 네비게이션 바와 탭 바를 동시에 가진 화면을 구성하는데
시행착오를 겪게 되었습니다.
일단 머릿 속에 떠오르는대로
'탭 바는 가장 상위에 위치시켜서 탭 선택을 통해 ViewController가 바뀌는 것 까지는
해결이 되었으니 당연히 각각의 ViewController에서 NavigationController의 인스턴스를
만들어서 사용하면 되겠지'
라고 생각했습니다.
결론부터 말씀드리면 그렇게 하셔도 됩니다.
다만 그렇게 할 경우 자주 질문하시는 '네비게이션 바를 통한 화면 전환시 탭 바를 사라지게'하는
방법에 별도의 코딩을 해주어야 하는 문제가 생깁니다.
하지만 IB를 통해 구성을 한 경우에는
[self.navigationController pushViewController:nextViewControlleranimated:YES];
를 호출하기 전에
nextViewController.hidesBottomBarWhenPushed = YES;
를 한 줄 추가해주시면 전환되는 화면에서 탭 바가 사라지게 됩니다.
4. 정리
- IB의 메인 화면에서 View Mode를 두 번 째나 세 번 째의 리스트 형태로 놓고 보아야 UI의 전체적인
그림이 보인다.
- 각각의 ViewController안에 NavigationController의 인스턴스를 만들어 사용해도 되나
그럴 경우 ViewController.hidesBottomBarWhenPushed = YES;가
정상적으로 적용되지 않는다.
이 때까지의 소스는 대략 다음과 같네요. 대부분 IB에서 작업을 진행해서 소스 코드 자체는
별거 없습니다.
// iPhotoDiaryAppDelegate.h
#import <UIKit/UIKit.h>
@class AppMainViewController;
@class CalendarGridViewController;
@class DiaryListViewController;
@class EventListViewController;
@interface iPhotoDiaryAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
UIWindow *window;
UITabBarController *tabBarController;
AppMainViewController *appMainViewController;
CalendarGridViewController *calendarView;
DiaryListViewController *diaryListController;
EventListViewController *eventListController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
@property (nonatomic, retain) IBOutlet AppMainViewController *appMainViewController;
@property (nonatomic, retain) IBOutlet CalendarGridViewController *calendarView;
@property (nonatomic, retain) IBOutlet DiaryListViewController *diaryListController;
@property (nonatomic, retain) IBOutlet EventListViewController *eventListController;
@end
//
// iPhotoDiaryAppDelegate.m
// iPhotoDiary
//
// Created by HYOUNG JUN WOO on 10. 4. 23..
// Copyright Mazdah.com 2010. All rights reserved.
//
#import "iPhotoDiaryAppDelegate.h"
#import "AppMainViewController.h"
#import "CalendarGridViewController.h"
#import "DiaryListViewController.h"
#import "EventListViewController.h"
@implementation iPhotoDiaryAppDelegate
@synthesize window;
@synthesize tabBarController;
@synthesize appMainViewController;
@synthesize calendarView;
@synthesize diaryListController;
@synthesize eventListController;
#pragma mark -
#pragma mark Application lifecycle
/*
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after app launch.
return YES;
}
*/
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
// [self copyDatabaseIfNeeded:@"iPhotoDiary.sqlite"];
}
/*
// Optional UITabBarControllerDelegate method.
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
}
*/
/*
// Optional UITabBarControllerDelegate method.
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed {
}
*/
#pragma mark -
#pragma mark Memory management
- (void)dealloc {
[tabBarController release];
[window release];
[appMainViewController release];
[calendarView release];
[diaryListController release];
[eventListController release];
[super dealloc];
}
@end
추가된 코드는 IBOutlet으로 연결될 탭 바 컨트롤러와 4개의 뷰 컨트롤러인데
사실 뷰 컨트롤러는 별도로 코딩을 해주지 않아도 IB에서 설정만 되어있으면
화면 전환이 이루어집니다.
5. 마무리
처음으로 이러한 작업(강좌 혹은 소스 분석)을 하다보니 영 내용이 두서가 없네요.
오늘의 내용은 대체로 소스 분석이라기 보다는 팁에 해당하는 내용이 주를 이루었습니다.
아마 대부분의 개발자 분들은 다 아시는 내용이실테고 혹시라도 이제 막 시작하시는 분들 중
모르셨던 분들에게나 도움이 될만한 내용이네요.
다음시간부터는 본격적으로 각각의 탭에 해당하는 기능들을 하나 하나 분석을 하도록 하겠습니다.
그럼 긴글 보아주셔서 감사하고 다음 시간에 뵙겠습니다.
'Development > iPhotoDiary(BabyPhotoDiary)' 카테고리의 다른 글
[옛 글] [실전 소스 분석] 3. 벌써 Core Data야??? (0) | 2013.07.18 |
---|---|
[옛 글] [업데이트] iPhotoDiary 1.1 (0) | 2013.07.18 |
[옛 글] [실전 소스 분석] 1. 나는 왜 iPhotoDiary를 만들게 되었나. (0) | 2013.07.18 |
[옛 글] [실전 소스 분석] iPhotoDiary 소스 분석을 시작합니다. (0) | 2013.07.18 |
[옛 글] iPhotoDiary 개발 로드맵 (0) | 2013.07.17 |