Posted
Filed under 분류없음

NavigationController
NavigationController는 객체의 계층적 구조를 관리하는 NavigationBar 인터페이스를 위한 컨트롤러입니다.
NavigationController는 ViewController들을 스택에 저장하여 관리합니다.
Navigation Based 프로젝트는 기본적으로 UITableviewController로 부터 상속받은 rootViewController를 생성해서 이를 가지고 ViewController 들을 관리합니다.


Navigation Stack 관리 메서드
스택에 추가
-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
추가된 뷰 컨트롤러가 최상단에 배치되게 됩니다.


스택에서 제거
-(void)popViewControllerAnimated:(BOOL)animated
현재 뷰 컨트롤러를 제거하고 이 뷰 컨트롤러를 호출한 뷰 컨트롤러가 화면에 나타나게 됩니다.


루트를 제외한 모든 뷰 컨트롤러 제거
-(NSArray *) popToRootViewControllerAnimated:(BOOL)animated
루트 뷰 컨트롤러를 제외한 모든 뷰 컨트롤러를 제거하고 이를 NSArray로 리턴


지정한 뷰 컨트롤러를 만날 때 까지 제거
-(NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated


Navigation Controller의 멤버
-(id)initWithRootViewController:(UIViewController *)rootViewController
초기화 할 때 사용하는 메서드로 Root로 사용할 뷰 컨트롤러 객체를 대입

(UIViewController *)topViewController - 최상위 뷰 컨트롤러
(UIViewController *)visibleViewController - 현재 보여지는 뷰 컨트롤러
(NSArray *)viewControllers - 스택에 있는 모든 뷰 컨트롤러들
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated - 뷰 컨트롤러 배열을 대입하는 메서드

UINavigationBar *navigationBar - 네비게이션 바로 읽기 전용
- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated
네비게이션 바의 보여주는 옵션을 설정하는 메서드


예제
NaviTest1_기초.zip

1. Navigation-Based Application 프로젝트 생성(NaviTest)

2. RootViewController.m  파일에 viewDidLoad 메서드 재정의
-(void)viewDidLoad
{
 [super viewDidLoad];
    self.title = @"Navi Test";
}


accessory
accessoryType
- UITableViewCellAccessoryDisclosureIndicator
>로 표시되며 이벤트를 받지는 않습니다.
셀을 선택했을 때 호출되는 메서드를 이용해서 이벤트를 작성합니다.
- UITableViewCellAccessoryDetailDisclosureButton
버튼으로 표시되며 이벤트를 받을 수 있습니다.
이 때 버튼을 클릭했을 때
- (void)tableView:(UITableView *)tableView
accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
메서드가 호출됩니다.
- UITableViewCellAccessoryCheckmark
셀에 체크 박스를 표시해 줍니다.
셀을 선택했을 때 호출되는 메서드를 이용해서 체크 하는 경우가 많습니다.


accessoryView
accessoryView도 UIView 타입이므로 직접 작성한 UIView 타입의 변수나 하위
클래스의 객체를 대입 할 수 있습니다.
이 때는 accessoryView에 대입합니다.


예제
NaviTest2_Accessory.zip

1. 프로젝트에 UIViewController클래스로 부터 상속받은 클래스 2개 추가
Item1, Item2로 추가하고 View는 적절히 디자인

2.RootViewController.h 파일에 위의 2개 헤더파일을 import하고 변수 선언
#import <UIKit/UIKit.h>
#import "Item1.h"
#import "Item2.h"
@interface RootViewController : UITableViewController
{
 Item1 *sub1;
 Item2 *sub2;
}
@end

3.RootViewController.m 파일의 메서드 수정
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {   
    static NSString *CellIdentifier = @"Cell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
     if(indexPath.row == 0)
  cell.textLabel.text = @"첫번째 셀";
 else
  cell.textLabel.text = @"두번째 셀";
     cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    return cell;
}
//셀을 선택했을 때 호출되는 메서드
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
 if(indexPath.row == 0)
 {
  if(sub1 == nil)
   sub1 = [[Item1 alloc]init];
  [self.navigationController pushViewController:sub1 animated:YES];
 }
 if(indexPath.row == 1)
 {
  if(sub2 == nil)
   sub2 = [[Item2 alloc]init];
  [self.navigationController pushViewController:sub2 animated:YES];
 }
}

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


예제
1. 셀을 출력하는 메서드 수정
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
    if(indexPath.row == 0)
 {
  cell.textLabel.text = @"첫번째 셀";
 }
 else
 {
  cell.textabel.text = @"두번째 셀";
 }
    cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
    return cell;
}

2. 버튼을 누를 때 호출되는 메서드 생성
//DetailDisclosureButton을 클릭했을 때 호출되는 메서드
- (void)tableView:(UITableView *)tableView
  accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
 NSString * msg = [NSString stringWithFormat:@"%d번째 선택", indexPath.row];
 UIActionSheet * sheet = [[UIActionSheet alloc]initWithTitle:msg
   delegate:nil cancelButtonTitle:@"확인" destructiveButtonTitle:nil
   otherButtonTitles:nil];
 [sheet showInView:self.view];
 [sheet release];
}


V체크 표시하기 예제
1. 셀을 출력하는 메서드 수정
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
    if(indexPath.row == 0)
  cell.textLabel.text = @"첫번째 셀";
 else
  cell.textLabel.text = @"두번째 셀";
    return cell;
}


2. 셀을 선택했을 때 호출되는 메서드 수정
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
        UITableViewCell *Cell = [tableView cellForRowAtIndexPath:indexPath];
        if(Cell.accessoryType == UITableViewCellAccessoryCheckmark)
  {
   Cell.accessoryType = UITableViewCellAccessoryNone;
   [tableView deselectRowAtIndexPath:indexPath animated:YES];
  }
  else
   Cell.accessoryType = UITableViewCellAccessoryCheckmark;
}

Alert 박스 표시하기 예제
TabNavigation1_accessory.zip

1. Window-BasedApplication 프로젝트 생성(TabNavigation)


2. TabNavigationAppDelegate.h 파일에 변수 선언 및 프로퍼티 생성
@interface TabNavigationAppDelegate : NSObject <UIApplicationDelegate>
{
    UIWindow *window;
    UITabBarController * mainController;
}
@property (nonatomic, retain) IBOutlet UITabBarController * mainController;
@property (nonatomic, retain) IBOutlet UIWindow *window;
@end

3. TabNavigationAppDelegate.m 파일에 @synthesize 지정
@synthesize mainController;


4. TabNavigationAppDelegate.m 파일의 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 메서드에 추가
[window addSubview:mainController.view];


5. TabNavigationAppDelegate.m 파일의 dealloc 메서드에 추가
[mainController release];

6. MainWindow.xib 파일에 TabBarController를 추가하고 TabNavigationAppDelegate의 mainController 변수 연결

7. MainWindow.xib의 TabBarController의 첫번째 아이템의 Class를 NavigationController로 변경

8. UITableViewController로 부터 상속받는 클래스 추가(CustomAccessory)


9. MainWindow.xib의 TabBarController의 첫번째 아이템의 ViewController에 CustomAccessory를 지정

10.CustomAccessory.h 파일에 변수 선언
#import <UIKit/UIKit.h>
@interface CustomAccessory : UITableViewController
{
  NSArray * team;
}
@property (nonatomic, retain)NSArray * team;
@end

11.CustomAccessory.m 파일의 dealloc메서드 작성
- (void)dealloc
{
     [team release];
     [super dealloc];
}

12.CustomAccessory.m 파일에서 @synthesize지정 과 데이터 초기화
@synthesize team;
- (void)viewDidLoad
{   
 NSDictionary *dic1 = [[NSDictionary alloc] initWithObjectsAndKeys:
                          @"KIA", @"Team", @"1위", @"Rank", nil];
 NSDictionary *dic2 = [[NSDictionary alloc] initWithObjectsAndKeys:
                          @"SK", @"Team", @"2위", @"Rank", nil];
 NSDictionary *dic3 = [[NSDictionary alloc] initWithObjectsAndKeys:
                          @"두산", @"Team", @"3위", @"Rank", nil];
 NSDictionary *dic4 = [[NSDictionary alloc] initWithObjectsAndKeys:
    @"롯데", @"Team", @"4위", @"Rank", nil];
 NSDictionary *dic5 = [[NSDictionary alloc] initWithObjectsAndKeys:
    @"삼성", @"Team", @"5위", @"Rank", nil];
 NSDictionary *dic6 = [[NSDictionary alloc] initWithObjectsAndKeys:
    @"LG", @"Team", @"6위", @"Rank", nil];
 team = [[NSArray alloc] initWithObjects:dic1, dic2,  dic3, dic4, dic5, dic6, nil];  
    [dic1 release];
   [dic2 release];
    [dic3 release];
   [dic4 release];
    [dic5 release];
   [dic6 release];
   [super viewDidLoad];   
}

13.CustomAccessory.m 파일의 섹션 만드는 메서드 재정의
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

14.CustomAccessory.m 파일의 행을 만드는 메서드 재정의
- (NSInteger)tableView:(UITableView *)tableView
 numberOfRowsInSection:(NSInteger)section
{
    return [self.team count];
}

15.CustomAccessory.m 파일의 셀 만드는 메서드 재정의
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  static NSString *CellTableIdentifier = @"CellTableIdentifier ";
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
         CellTableIdentifier];
  if (cell == nil)
  {
   cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
             reuseIdentifier: CellTableIdentifier] autorelease];
   UIImage *buttonUpImage = [UIImage imageNamed:@"arrowleft.png"];
   UIImage *buttonDownImage = [UIImage imageNamed:@"arrowdown.png"];
   UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
   
    button.frame = CGRectMake(0.0, 0.0, buttonUpImage.size.width, buttonUpImage.size.height);
    [button setBackgroundImage:buttonUpImage forState:UIControlStateNormal];
    [button setBackgroundImage:buttonDownImage forState:UIControlStateHighlighted];
    [button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
    cell.accessoryView = button;
    }
  NSUInteger row = [indexPath row];
  NSDictionary *dic = [self.team objectAtIndex:row];
  cell.textLabel.text = [dic objectForKey:@"Team"];
  return cell;
}


16.CustomAccessory.m 파일에 click메서드 작성
- (void)click:(id)sender
{
    UIButton *button = (UIButton *)sender;
    UITableViewCell *Cell = (UITableViewCell *)[button superview];
    NSUInteger row = [[self.tableView indexPathForCell:Cell] row];
   NSDictionary *dic = [self.team objectAtIndex:row];
   NSString * msg = [dic objectForKey:@"Rank"];
   UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"순위"
       message:msg delegate:nil   cancelButtonTitle:@"확인"  otherButtonTitles:nil];
    [alert show];
    [alert release];
}

17.프로젝트에 2개의 그림 파일 삽입(arrowleft.png, arrowdown.png)

NavigationItem
- NavigationItem은 네이비게이션 바에 나오는 아이템입니다.

- 클래스는 UINavigationItem 타입이며 UIViewController의 프로퍼티로 존재하며 다시 이 항목은 UIBarButtonItem *leftButtonItem, UIView *titleView, UIBarButtonItem *rightBarButtonItem 프로퍼티를 소유하고 있습니다.

- UIBarButtonItem의 초기화
문자열 초기화
initWithTitle:(NSString *)title style:모양 target:이벤트 처리 메서드 소유 객체
action:@selector(이벤트 처리 메서드)

시스템 버튼 이용
initWithBarButtonSystemItem:시스템 버튼 target:이벤트 처리 메서드 소유 객체
action:@selector(이벤트처리메서드)

네비게이션 바 버튼 테스트 예제
TabNavigation2_navigationItem.zip

1. CustomAccessory.m 파일의 ViewDidLoad 메서드에 추가
     self.title = @"네비바 버튼 테스트";
 UIBarButtonItem *button = [[[UIBarButtonItem alloc]initWithTitle:@"버튼 클릭" style:UIBarButtonItemStylePlain target:self action:@selector(naviBarClick)]autorelease];
 self.navigationItem.rightBarButtonItem = button;

2. CustomAccessory.m 파일에 메서드 추가
-(void)naviBarClick
{
 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"네비게이션 바 버튼"
                                   message:@"클릭"     delegate:nil
                                   cancelButtonTitle:@"확인" otherButtonTitles:nil];
    [alert show];
    [alert release];
}


NavigationBar에 segmented 달기
TabNavigation3_segmented.zip

1.CustomAccessory.h 파일에 변수 선언
NSInteger rowNumber;


2.CustomAccessory.m 파일에 행을 선택했을 때 호출되는 메서드 재정의
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
 rowNumber = indexPath.row;
}

3.CustomAccessory.m 파일의 viewDidLoad에 추가
     NSArray *buttonName = [NSArray arrayWithObjects:@"팀",@"순위",nil];
 UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:buttonName];
 segmentedControl.momentary = YES;
 segmentedControl.autoresizingMask = UIViewAutoresizingFlexibleWidth;
 segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
 segmentedControl.frame = CGRectMake(0.0, 0.0, 400, 30);
 [segmentedControl addTarget:self action:@selector(segmentClick:) forControlEvents:UIControlEventValueChanged];
 self.navigationItem.titleView = segmentedControl;
 [segmentedControl release];
 rowNumber = -1;

4.CustomAccessory.m 파일에 메서드 추가
-(void)segmentClick:(id)sender
{
 NSString * msg;
 if(rowNumber >=0 && rowNumber < [team count]){
  NSDictionary *dic = [self.team objectAtIndex:rowNumber];
  if ([sender selectedSegmentIndex] ==0)
   msg = [dic objectForKey:@"Team"];
  else if ([sender selectedSegmentIndex] ==1)
   msg = [dic objectForKey:@"Rank"]; 
  UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"프로야구"
        message:msg delegate:nil
         cancelButtonTitle:@"확인" otherButtonTitles:nil];
    [alert show];
    [alert release];
 }
 else{
 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"실패"
         message:@"선택한 행 없음"    delegate:nil
         cancelButtonTitle:@"확인"       otherButtonTitles:nil];
    [alert show];
    [alert release];
 }
}


상호 의존적인 데이터 출력
- 상호 의존적인 데이터를 출력할 때는 네비게이션 컨트롤러를 적절히 이용하면 됩니다.
- 새로운 테이블 뷰 컨트롤러를 생성해서 테이블에서 메인 데이터를 클릭했을 때 그 서브 데이터를 화면에 출력하는 형태를 취하면 됩니다.
- 상위 데이터를 출력하는 곳에서 데이터를 선택할 때 선택된 데이터를 서브 데이터를 출력하는 곳으로 넘겨주고 서브 데이터를 출력하는 새로운 뷰에서는 viewWillAppear에서 데이터를 다시 reload 하면 됩니다.

예제
TabNavigation1_subView.zip

1. 앞의 프로젝트에서 탭 바 아이템 두번째의 class를 Navigation Controller 로 수정

2. UIViewController로 부터 상속받는 클래스(RootViewController)를 추가하고 두번째 탭 바 아이템의 ViewController에 연결

3. RootViewController.xib 파일의 View에 테이블 뷰를 추가하고 delegate와 datasource 지정

4. RootViewController.h 파일에 변수를 생성하고 프로퍼티 생성
@class SubViewController;
@interface RootViewController : UITableViewController {
NSMutableArray * data;
SubViewController * subView;
}
@property(nonatomic, retain) NSMutableArray * data;
@property(nonatomic, retain)SubViewController * subView;
@end

5. RootViewController.m 파일에 synthesize지정과 loadView에서 배열을 초기화하고 dealloc에서 release
#import "SubViewController.h"
@implementation RootViewController
@synthesize data, subView;
- (void)loadView
{
 [super loadView];
 NSMutableArray *KIA;
 NSMutableArray *SK;
 NSMutableArray *HD;
 NSMutableArray *LG;
 KIA = [NSMutableArray arrayWithObjects:@"윤석민", @"이용규", @"이종범", nil];
 SK = [NSMutableArray arrayWithObjects:@"김광현", @"김재현", nil];
 HD = [NSMutableArray arrayWithObjects:@"김시진", nil];
 LG = [NSMutableArray arrayWithObjects:@"이택근", @"이병규", @"봉중근", nil];
 NSDictionary *Dic1, *Dic2, *Dic3, *Dic4;
 Dic1 = [[NSDictionary alloc] initWithObjectsAndKeys:@"KIA", @"Team", KIA, @"data", nil];
 Dic2 = [[NSDictionary alloc] initWithObjectsAndKeys:@"SK", @"Team", SK, @"data", nil];
 Dic3 = [[NSDictionary alloc] initWithObjectsAndKeys:@"HD", @"Team", HD, @"data", nil];
 Dic4 = [[NSDictionary alloc] initWithObjectsAndKeys:@"LG", @"Team", LG, @"data", nil];
 data = [[NSMutableArray alloc] initWithObjects:Dic1, Dic2, Dic3, Dic4, nil];
 [Dic1 release];
 [Dic2 release];
 [Dic3 release];
 [Dic4 release];
 self.title = @"프로야구";
}
- (void)dealloc
{
[self.data release];
[self.subView release];
    [super dealloc];
}

6. RootViewController.m 파일에 데이터 출력 메서드 수정
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.data count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
   
    static NSString *CellIdentifier = @"Cell";
   
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
 NSDictionary *Dic = [self.data objectAtIndex:indexPath.row];
    cell.textLabel.text = [Dic objectForKey:@"Team" ];
 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    return cell;
}


7. RootViewController.m 파일에 서브 데이터 출력을 위한 메서드(행 선택) 작성
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
 {
 if (self.subView == nil)
 {
  SubViewController *temp = [[SubViewController alloc] initWithStyle:UITableViewStylePlain ];
  self.subView = temp;
  [temp release];
 }
 self.subView.subData = [self.data objectAtIndex:indexPath.row];
 [[self navigationController] pushViewController:subView animated:YES];
}

8. 서브 데이터를 출력할 새로운 ViewController 추가(SubViewController – UITableViewController로 부터 상속)

9. SubViewController.h 파일에 변수 생성 및 프로퍼티 설정
NSDictionary * subData;
@property (nonatomic, retain)NSDictionary * subData;

10. SubViewController.m 파일에  synthesize 지정과 데이터 출력 메서드 수정
@synthesize subData;
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.title = [self.subData objectForKey:@"Team"];
    [self.tableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
      NSMutableArray *ar = [self.subData objectForKey:@"data"];   
 return [ar count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
    }
     NSMutableArray  *ar = [self.subData objectForKey:@"data"];
     cell.textLabel.text = [ar objectAtIndex:indexPath.row];
    return cell;
}
- (void)dealloc
{
 [subData release];
    [super dealloc];
}


셀 편집
- 테이블 뷰 컨트롤러는 자체적으로 Edit 버튼과 기능을 제공합니다.
- editButtonItem이 편집 버튼입니다.
- Edit 버튼을 누르면 호출 되는 메서드
- (void)setEditing:(BOOL)editing animated:(BOOL)animated

- 셀의 왼쪽에 편집 모드 버튼을 배치할 수 있는 메서드
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath

- 삭제(Delete)나 삽입(+) 버튼을 누르면 호출되는 메서드
- (void)tableView:(UITableView *)aTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 


예제
TabNavigation2_edit.zip

1. SubViewController.m 파일에 viewDidLoad 메서드 재정의
- (void)viewDidLoad
{
    [super viewDidLoad];
 self.navigationItem.rightBarButtonItem = [self editButtonItem];
}

2.SubViewController.m 파일의 행 개수 설정 메서드 수정
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSMutableArray  *ar = [self.subData objectForKey:@"data"];
    if(self.isEditing)
  return [ar count]+1;
 else
  return [ar count];
}

3. SubViewController.m 파일의 셀 표시 메서드 수정
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
    }
 NSMutableArray  *ar = [self.subData objectForKey:@"data"];
 if([self isEditing] && indexPath.row == [ar count])
  cell.textLabel.text = @"새 데이터 추가";
 else  
 cell.textLabel.text = [ar objectAtIndex:indexPath.row];
    return cell;
}

4. SubViewController.m 파일의 Edit 버튼을 눌렀을 때 호출되는 메서드 재정의
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
    [self.tableView beginUpdates];
 [super setEditing:editing animated:YES];
 NSMutableArray  *ar = [self.subData objectForKey:@"data"];
 if (editing)
 {
  [self.tableView insertRowsAtIndexPaths:
   [NSArray arrayWithObject:[NSIndexPath indexPathForRow:[ar count] inSection:0] ]
         withRowAnimation:UITableViewRowAnimationTop];
 }
 else
 {
  [self.tableView deleteRowsAtIndexPaths:
   [NSArray arrayWithObject:[NSIndexPath indexPathForRow:[ar count] inSection:0] ]
         withRowAnimation:UITableViewRowAnimationTop];
 }
    [self.tableView endUpdates];
}


5. SubViewController.m 파일에서 셀의 왼편에 보여질 아이콘 설정
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
  editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
 NSMutableArray  *ar = [self.subData objectForKey:@"data"];
 //셀이 편집 모드가 아니면 편집 모드 아이콘을 출력하지 않음
 if ([self isEditing] == NO)
  return UITableViewCellEditingStyleNone;
 //편집 모드이고 마지막행이라면 insert아이콘을 출력
 if ([self isEditing] && indexPath.row == [ar count])
  return UITableViewCellEditingStyleInsert;
 //그 이외의 경우는 delete아이콘을 출력
 return UITableViewCellEditingStyleDelete;
}

6. SubViewController.m 파일에서 실제 편집 버튼을 누를 때 호출되는 메서드 작성
- (void)tableView:(UITableView *)tableView
 commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
 forRowAtIndexPath:(NSIndexPath *)indexPath
{   
 NSMutableArray *ar = (NSMutableArray *)[self.subData objectForKey:@"data"];
    if (editingStyle == UITableViewCellEditingStyleDelete)
 {
  [ar removeObjectAtIndex:indexPath.row];
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
 else if (editingStyle == UITableViewCellEditingStyleInsert)
 {
  CellEditViewController* editView = [[CellEditViewController alloc]init];
  editView.title = @"추가";
  editView.content = ar;
  [self.navigationController pushViewController:editView animated:YES];
  [editView release];
 }
}


7. SubViewController.m 파일의 상단에 CellEditViewController.h 파일 import

8. 삽입 버튼을 누를 때 호출할 UIViewController로 부터 상속받는 클래스 생성(CellEditViewController)


9. CellEditViewController.h 파일에 변수 및 프로퍼티 생성
@interface CellEditViewController : UIViewController
 {
 IBOutlet UITextField *nameField;
 NSMutableArray *content;
}
@property (retain) NSMutableArray *content;

-(void) save;
-(void) cancel;
@end

10. CellEditViewController.m 파일에 @synthesize 지정과 viewDidLoad메서드 재정의
@synthesize content;
- (void)viewDidLoad
{
 [super viewDidLoad];
 self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancel)];
 self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(save)];
}


11. CellEditViewController.m 파일에 save와  cancel 메서드 추가
-(void) cancel
{
 [self.navigationController popViewControllerAnimated:YES];
}

-(void) save
{
  [self.content addObject:nameField.text];
   [self.navigationController popViewControllerAnimated:YES];
}


12. CellEditViewController.m 파일의 dealloc 메서드에 추가
     [nameField release];
     [content release];


13. CellEditViewController.m 파일의 viewWillAppear 메서드 재정의
- (void)viewWillAppear:(BOOL)animated
{
     [nameField becomeFirstResponder];
}

14. CellEditViewController.m 파일의 view에 TextField를 추가하고 변수 연결

항목 이동
이동 가능 여부를 리턴해주는 메서드
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
이동 중 호출되는 메서드
- (NSIndexPath *)tableView:(UITableView *)tableView
targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
이동 종료 후 호출되는 메서드
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
toIndexPath:(NSIndexPath *)toIndexPath 메서드에서 데이터 재배치를 합니다.

예제
TabNavigation3_moveEdit.zip

SubViewController.m 파일에서 이동가능 하게 하는 메서드 작성
//이동 가능 여부를 설정하는 메서드
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
 NSMutableArray *ar = (NSMutableArray *)[self.subData objectForKey:@"data"];
 //새 데이터 추가(맨 마지막 행)만 이동이 불가능하도록 설정
 if (indexPath.row < [ar count])
  return YES;
 return NO;
}
//이동이 시작될 때 호출되는 메서드
- (NSIndexPath *)tableView:(UITableView *)tableView
       targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
    toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
 NSMutableArray *ar = (NSMutableArray *)[self.subData objectForKey:@"data"];
 if (proposedDestinationIndexPath.row >= [ar count])
 {
        return [NSIndexPath indexPathForRow:([ar count] - 1) inSection:0];
    }
    return proposedDestinationIndexPath;
}
//셀의 이동이 끝난 후 호출되는 메서드
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
   toIndexPath:(NSIndexPath *)toIndexPath
{
 NSMutableArray *ar = (NSMutableArray *)[self.subData objectForKey:@"data"];
 id toMove = [[ar objectAtIndex:fromIndexPath.row] retain];
 [ar removeObjectAtIndex:fromIndexPath.row];
 [ar insertObject:toMove atIndex:toIndexPath.row];
 [toMove release];
}


셀의 내용 편집
- 셀을 편집하고자 하는 경우에는 일반적으로 Add와 동일한 뷰 컨트롤러를 호출하여 편집한 후 저장하는 형태를 취하게 됩니다.
- 테이블 뷰의 셀은 기본적으로 편집 상태에서는 선택이 되지 않으므로 편집 상태에서도 선택이 가능하도록 옵션을 조정해 주어야 합니다.

테이블뷰객체.allowsSelectionDuringEditing = YES;


예제
1. 셀의 편집 가능여부를 리턴하는 메서드 작성(SubViewController.m)
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
      tableView.allowsSelectionDuringEditing = YES;
 return YES;
}

2. 셀을 선택했을 때 호출되는 메서드 수정
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
 NSMutableArray *ar = (NSMutableArray *)[self.subData objectForKey:@"data"];
 if ([self isEditing])
 {
  CellEditViewController* editView = [[CellEditViewController alloc]init];  
  if (indexPath.row == [ar count]) {
   editView.value = nil;
   editView.title = @"추가";
  }
  else
       {
   editView.value = [ar objectAtIndex:indexPath.row];
                editView.sel = indexPath.row;
   editView.title = @"편집";
  }
  editView.content = ar;
  [self.navigationController pushViewController:editView animated:YES];
  [editView release];
 }
 else
 {
  [self.tableView deselectRowAtIndexPath:indexPath animated:NO];
 }
}


3. CellEditViewController.h 파일에 변수 추가
NSString *value;
int sel;


4. CellEditViewController.h 파일에 프로퍼티 추가
@property(nonatomic, retain)NSString *value;
@property(nonatomic)int sel;

5. CellEditViewController.m 파일에 synthesize 추가
@synthesize value;
@synthesize sel;

6. viewWillAppear 메서드 수정
- (void)viewWillAppear:(BOOL)animated
{
 if (self.value)
 {
  [nameField setText:self.value];
 }
 [nameField becomeFirstResponder];
}


7. save 메서드 수정
-(void) save
{
 if(self.value)
 {
   [self.content replaceObjectAtIndex:sel withObject:nameField.text];
 }
 else
  [self.content addObject:nameField.text];
 [self.navigationController popViewControllerAnimated:YES];
}


[원문] - http://wwwww.kr/35084

2011/06/20 13:48 2011/06/20 13:48