최초 작성일 : 2012/01/27 08:51


처음으로 Xcode 4.2에서 프로젝트를 생성하고부터는 나날이 하는 일이 삽질이다...-.-

역시 대체로 문제가 되는 것은 새로 도입된 스토리 보드...

전체적인 화면의 흐름을 한 눈에 보면서 작업한다는 점에서는 더할나위 없이 좋지만
아무래도 새로 생긴 기능이다 보니 삽질을 피해갈 수는 없다.

오늘은 아주 간단한 삽질 하나 소개(!?)한다.

최초 프로젝트를 생성할 때는 탭바 베이스의 화면으로 시작을 했다.
그래서 아래와 같은 스토리 보드가 생성이 되었다.





최초에는 탭바 아이템 2개가 기본으로 생성이 되었고 나머지 하나는 직접 생성한 것으로
이에 대한 삽질은 지난 번에 소개를 하였다.

그런데 작업을 하다보니 기왕 하는 김에 Universal 앱을 만들고픈 욕심이 생겼다.
그래서 아이패드를 고려한 화면으로 재구성이 필요하였다.

결국 아이패드에서는 좀 휑~해보이는 탭바를 포기하고 분활 화면 형태로 가기로
결정을 했다. 그리고 과감하게(또는 무식하게) 탭바 컨트롤러라고 표시된 스토리보드상의
오브젝트를 지워버렸다.





그리고는 의기양양하게 다시 Run!

그러나...RootViewController가 없다는 메시지와 함께 화면은 먹통...

일단 이전 방식을 염두에 두고 AppDelegate 소스를 보았다.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

    // Override point for customization after application launch.;

    return YES;

}


어...좀 깨끗하네...-.-
이 것 때문인가...? 하고서는 열심히 그전 처럼 코딩을 했다.
rootViewController로 사용할 뷰 컨트롤러의 인스턴스를 만들어서
window.rootViewController에 넣어주고 makeKeyAndVisible도 호출해주고...

그러나 역시 먹통...

다시 추가한 코드 싹 지우고 구글링 시작...
그리고 구글신의 도움으로 원인 발견...

일단 탭바 컨트롤러를 삭제한 상태에서의 스토리 보드 화면은 아래와 같다.




탭바를 지우기 전과 달라진 점이라면 당근 탭바 컨트롤러가 사라졌고 동시에 같이
사라진 놈이 하나 있다. 틀린 그림 찾기나 해볼까~?

바로 탭바컨트롤러의 좌측에 붙어있던 화살표(첫 번 째, 두 번 째 그림 참고).
그렇다 바로 이 화살표가 rootViewController를 지정해 주는 역할을 하고 있었던
것이다.

그럼 이 화살표는 어떻게 만드느냐.
스토리 보드 화면 우측창에서 Attribute 인스펙터를 선택하고 중간정도에 보면
체크박스 4개가 보인다. 그 중 맨 위에 Initial Scene이라는 타이틀이 붙어있는 것이
바로 rootViewController를 지정하는 역할을 한다. 이 것을 체크하니 아래와 같이
FirstViewController의 좌측에 화살표가 생기고 Run을 하니 화면이 정상적으로
나왔다.




이상으로 오늘의 짧고 굵었던(은 좀 아닌 것 같고) 삽질기를 마친다.

블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^

최초 작성일 : 2010/03/28 08:38



RootViewController.h


//UITableViewController를 상속받은 RootViewController 선언

@interface RootViewController : UITableViewController {

//클래스 변수로 NSArray 타입의 timeZoneNames선언

NSArray *timeZoneNames;

}


//접근자와 변경자 자동 선언 키워드

@property (nonatomicretain) NSArray *timeZoneNames;


@end




RootViewController.m

//선언부 import

#import "RootViewController.h"

#import "SimpleTableViewAppDelegate.h"



@implementation RootViewController

//접근자와 변경자 자동 구현 키워드

@synthesize timeZoneNames;


//UIViewController에 있는 함수. 메모리에 컨트롤러의 뷰가 로드된 후 호출됨

- (void)viewDidLoad {

     //title은 UIViewController에 있는 속성

   //NSLocalizedString : Foundation Function. NSBundle에 있는

     //localizedStringForKey:value:table: 함수를 실행시켜

  //지역화된 문자열을 반환Time Zones라는 테이블로부터

     //Time Zones title이라는 값을 가져온다.

self.title = NSLocalizedString(@"Time Zones"@"Time Zones title");

}


//UITableView에 구현된 UITableViewDataSource protocol에 있는 함수. 

//테이블 뷰에 섹션이 몇개 있는지 갯수를 반환

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

// There is only one section.

return 1;

}



//UITableView에 구현된 UITableViewDataSource protocol에 있는 함수. 

//인자로 넘어간 테이블 뷰 내의 섹션에 몇개의 row가 있는지를 반환

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

// Return the number of time zone names.

//timeZoneNames배열의 내용이 그대로 테이블 뷰를 구성하므로 그 크기를 반환함

return [timeZoneNames count];

}


//UITableView에 구현된 UITableViewDataSource protocol에 있는 함수. 

//인자로 넘어간 테이블 뷰의 특정 위치(인자로 넘어간 indexPath)에 cell을 삽입하는 함수.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *MyIdentifier = @"MyIdentifier";

// Try to retrieve from the table view a now-unused cell with the given identifier.

//인자로 넘어간 문자열을 이름으로 갖는 재사용 가능한 테이블 뷰 셀을 반환.

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

// If no cell is available, create a new one using the given identifier.

//만일 재사용 가능한 셀이 없으면 새로운 셀을 생성

if (cell == nil) {

// Use the default cell style.

//alloc으로 생성하였으므로 반드시 release해주어야 함. 그러나 cell은 다른 위치에서 참조되고 사용되므로

//autorelease를 설정하여 처리함

//UITableViewCellStyleDefault라는 셀 스타일과 MyIdentifier라는 식별자로 셀을 초기화 함

cell = [[[UITableViewCell allocinitWithStyle:UITableViewCellStyleDefaultreuseIdentifier:MyIdentifier] autorelease];

}

// Set up the cell.

//timeZoneNames 배열의 인자로 받은 위치에 있는 문자열을 추출하고

NSString *timeZoneName = [timeZoneNames objectAtIndex:indexPath.row];

//추출한 문자열을 셀의 text 속성에 넣는다.

cell.textLabel.text = timeZoneName;

return cell;

}


/*

 To conform to Human Interface Guildelines, since selecting a row would have no effect (such as navigation), make sure that rows cannot be selected.

 */

//인자로 받은 tableView의 indexPath위치에 있는 cell이 선택되었음을 delegate에게 전달한다.

//이 예제에서는 cell 선택에 대한 내용을 처리하지 않으므로 그냥 nil을 리턴한다.

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {

return nil;

}


//메모리 해제

- (void)dealloc {

[timeZoneNames release];

[super dealloc];

}


@end


[Notice]
UITableView는 2개의 protocol을 구현하고 있는데
UITableViewDelegate는 테이블 뷰의 설정을 처리혹
UITableViewDataSource는 테이블 뷰의 각 행의 데이터를 처리한다.

블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^