* 테이블
- 테이블은 데이터의 목록을 표시한다.
- 테이블 목록의 각각의 항목은 행(row), 각 행마다 열(column)은 하나만 있다.
- 테이블 뷰는 테이블에 있는 데이터를 보여주는 뷰이고, UITableView 클래스의 인스턴스이다.
테이블에 각각의 행은 UITableViewCell 클래스로 구현된다.
그래서 테이블 뷰는 테이블의 전체적인 모양을 담당하는 객체이고, 테이블 뷰 셀이 테이블의 각각의 행을 그리는 일을 담당한다.
- 테이블 뷰는 테이블의 데이터를 저장하는 역할은 하지 않는다.
단지 현재 보여주는 행을 그릴 때 필요한 데이터만 저장하낟.
- 테이블 뷰의 설정 데이터는 UITableViewDelegate 프로토콜을 따르는 객체에서 구하고,
각 행의 데이터는 UITableViewDataSource 프로토콜을 따르는 객체로부터 얻는다.
- 테이블 뷰에는 두가 기본 스타일이 존재.
그룹으로 묶은 방식(Group Table) : 그룹으로 묶은 테이블의 각각의 그룹은 둥근 사각형에 둘러쌓인 행의 집합이다.
인덱스로 구분한 테이블(Indexed Table) : 둥근 사각형이 없는 테이블
- 테이블의 나누어진 영역이 데이터 소스에서는 섹션이다.
그룹으로 묶은 테이블에서 각 그룹은 섹션이다.
인덱스로 묶은 테이블에서는 데이터를 인덱스별로 묶은 것이 섹션이다.
* TableView Data Source
// 이것은 특정 섹션에 몇개의 행이 있는지 질의 하는데 사용한다.
-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInsection:(NSInteger)section
{
return [self.listData count]; // 여기서는 배열의 카운트를 리턴해 준다.
}
// 행을 그릴 필요가 있을 때 테이블 뷰가 이 메서드를 호출한다.
// NSIndexPath 로부터 행이나 섹션을 얻을 수 있다.
// 첫번째 인자인 tableView 는 현재 메서드를 호출한 테이블의 레퍼런스
// 두번째 인자는 NSIndexPath 의 객체
-(UITableViewCell *)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
/*
정적 문자열 인스턴스의 선언
이 문자열은 테이블 셀의 종류를 나타내는 키로 쓰인다.
여기에서는 셀의 종류가 하나만 있으므로 하나만 선언한다.
테이블 뷰는 아이폰의 작은 화면에 단지 몇개의 행만 표시할 수 있지만 테이블 자체는 훨씬 더 많은 데이터를 담을 수 있다.
테이블의 각 행은 UITableViewCell 의 인스턴스로 나타냄을 염두에 둔다.
또 UITableViewCell 은 UIView 의 하위 클래스인데 이는 각각의 행은 하위뷰를 가질 수 있다는 것을 의미한다.
테이블이 클 경우 현재 보이지 않더라도 각각의 행마다 하나의 테이블 뷰 셀을 유지한다면 이것은 엄청난 메모리 손실을 의미한다.
다행히테이블은 이런 방식으로 동작하지 않는다.
대신 테이블 뷰의 셀들이 스크롤되면서 화면에서 사라지게 되면 재 사용이 가능한 셀의 큐(queue)에 들어간다.
시스템의 메모리가 부족하면 테이블 뷰는 큐의 셀을 제거하지만 메모리 여유가 있는 한 다시 사용할 때를 대비해서 유지한다.
테이블 뷰 셀이 화면에서 밀려날 때마다 화면 반대편에 다른 셀을 보여줄 기회가 있다.
만약 새로운 행이 이전에 사라졌던 행 중에서 다시 사용하게 된 경우라면 시스템은 끊임없이 이러한 뷰를 만들고 해제하는 부담을 피할 수 있다.
이러한 방법을 사용하기 위해서 디큐(dequeued) 된 셀 중에서 필요한 타입을 테이블 뷰에서 얻어야 하는 데
이때 앞에서 아래에 선언한 NSString 식별자를 사용하는 것에 주목한다.
사실상 SimpleTableIdentifier 와 같은 종류의 재사용 가능한 셀을 요청하는 것이다.
*/
static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier";
// 테이블 뷰의 셀들이 스크롤 돼서 화면에서 사라지면 재사용 가능한 셀의 뷰(queue)에 들어간다.
// 새로운 행이 이전에 사라졌던 행 중에서 다시 사용하게 된다면 시스템은 끊임없이 이러한 뷰를 만들고 해제하는 부담을 피할 수 없다.
// 이러한 방법을 사용하기 위해서 디큐(dequeue) 된 셀 중에서 필요한 타입을 테이블 뷰에 얻어야 한다. (SimpleTableIdentifier)
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
/*
테이블 뷰가 여분의 셀이 전혀 없을 가능성도 있으므로 셀이 nil 인지 확인한다.
만약, nil 이라면 이전의 식별자 문자열을 사용해서 수동으로 새로운 테이블 뷰 셀을 만든다.
언젠가 여기서 만든 셀을 재사용할 수도 있으니 같은 종류인지 확인할 필요가 있다.
*/
if(cell == nil)
{
// 재사용 가능하게 동일한 셀로 만든다.
//default
// cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SimpleTabeIdentifier] autorelease];
/*
* 3.0 에서 추가된 detailTextLabel 을 사용하기 위해서 스타일을 변경한다.
* UITableViewCellStyleSubtitle
*/
// cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:SImpleTableIdentifier] autorelease];
/*
* UITableViewCellStyleValue1
* 이 스타일은 셀 이미지를 사용하지 않으므로 텍스트 레이블과 상세 레이블을 한줄에 배치하고 서로 대칭되도록 정렬한다.
*/
// cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:SimpleTableIdentifier] autorelease];
/*
* UITableViewCellStyleValue2
* 이 스타일은 셀에 대한 정보 설명을 위해 사용되는 레이블과 나란히 출력할 때 사용된다.
* 셀 아이콘을 보여줄 때는 나타나지 않지만, 세부 레이블을 텍스트 레이블의 왼쪽으로 배치한다.
*/
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:SimpleTableIdentifier] autorelease];
}
/*
이제 테이블 뷰에 넘겨 줄 테이블 뷰 셀을 만들었고, 보여주고 싶은 정보를 셀 안에 표시하는 것이 남았다.
그리고 테이블 뷰의 값에 접근하기 위해서는 어떤 행의 값을 사용할 것인지 결정해야 한다.
아래 구문은 받은 indexPath 의 row 로 얻은 int 를 배열의 인자로 사용한다.
*/
// 어떤 행의 값을 사용할 것인지 결정
NSUInteger row = [indexPath row];
// textLabel.text 는 오직 아이폰 SDK 3.0 이상에서만 동작한다.
cell.textLabel.text = [listData objectAtIndex:row];
// 폰트 크기 변경
cell.textLabel.font = [UIFont boldSystemFontOfSize: 50];
return cell;
}
매서드의 첫 번째 인자인 tableView 는 현재 매서드를 호출한 테이블의 레퍼런스(참조)이다.
이것은 여러 테이블용 데이터소스처럼 행동하는 클래스를 만들도록 해준다.
매서드의 두번째 인자는 NSIndexPath 의 개체임을 주목해야 한다.
이 객체를 사용해 테이블 뷰가 섹션과 행을 하나의 객체로 감싼다.
둘 다 int 값을 리턴하는 행 메서드나 섹션 메서드 가운데 하나를 호출하면 NSIndexPath 로부터 행이나 섹션을 얻을 수 있다.
* 각 행에 이미지 추가하기
-(UITableViewCell *)tableView:(UITableView *) cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier =@"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if(cell == nil)
{
cell = [[[[UITableViewCell alloc] initWithFrame:CGRectZero] reuseIdentifier:SimpleTableIdentifier] autorelease];
}
// cell 에 이미지를 추가한다.
// UIImage 는 파일 이름을 기반으로 캐쉬 기술을 사용하므로, 매번 새 이미지를 로딩하지 않을 것이다.
// 대신 캐쉬된 이미지를 사용할 것이다.
// 이미지는 셀의 텍스트 왼편에 보이며 셀이 선택 되었을 때 highlightedImage 에 명시된 이미지로 바뀐다.
UIImage *image = [UIImage imageName:@"star.png"];
cell.imageView.image = image;
// 해당 cell 이 선택되었을 때 이미지 추가
// UIImage *highlightedImage = [UIImage imageName:@"star2.png"];
// cell.imageView.highlightedImage = highlightedImage;
NSUInteger row = [indexPath row];
cell.textLabel.text = [listData objectAtIndex:row];
return cell;
}
[테이블 뷰 셀 스타일]
아이폰 SDK 3.0 이전 버전까지는 단일 셀 스타일로 제한되었고 3.0 부터 몇가지 기능을 표준 셀에 추가했다.
- 이미지 : 이미지는 특정 스타일의 한 부분으로 이미지는 셀 텍스트의 왼쪽에 보여진다.
- 텍스트 레이블 : 셀의 첫 번째 텍스트이다. 이전 버전에서 UITableViewCellStyleDefault 는 셀에 유일한 텍스트 레이블을 위해 사용되었다.
- 세부 텍스트 레이블 : 보통 설명을 위한 글이나 레이블을 형태로 사용되는 셀의 두 번째 텍스트이다.
//UITableViewCellStyleDefault 를 사용하면 설명을 위한 텍스트가 만들어지지 않는다.
if(row < 7)
cell.detailTextLabel.text = @"Mr. Ban";
else{
cell.detailTextLabel.text = @"Mr. Minam";
}
* UITableViewCellStyle 의 종류
- 하위 제목 스타일 적용 : 하위 제목은 작은 글자로 텍스트 레이블을 설명하는 글을 담고 있으며,
텍스트 레이블 밑에 회색 컬러를 사용하여 출력된다.
UITableViewCellStyleDefault 를 UITableViewCellStyleSubtitle 로 변경해보면
detailTextLabel 을 확인할 수 있다.
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:SimpleTableIdentifier] autorelease];
cell.detailTextLabel.text = @"xxxxxx";
- 텍스트 레이블과 상세 레이블을 한 줄에 배치하고 서로 대칭되도록 정렬 : 텍스트 레이블은 검은색으로 셀의 왼쪽에 나타나고,
상세 텍스트는 파란색으로 셀의 오른쪽에 나타난다.
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:SimpleTableIdentifier] autoreleas];
cell.detailTextLabel.text = @"xxxxxx";
- 셀에 대한 정보를 설명하기 위해 사용되는 레이블과 나란히 출력할 때 사용된다.
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:SimpleTableIdentifier] autorelease];
cell.detailTextLabel.text = @"xxxxxx";
[테이블 델리게이트]
델리게이트의 목적은 테이블 뷰의 모습을 설정하고 특정 사용자 상호작용을 처리하는 것이다.
* Delegate 를 사용해서 몇몇 행은 들어쓰기 (Indent)
#pragma mark -
#pragma mark Table Delegate Methods
// 들어쓰기 레벨 설정
-(NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 각 행의 행 번호만큼 들여쓰기 레벨을 설정하도록 한다.
NSUInteger row = [indexPath row];
return row ;
}
* 특정 행 선택 불가능 하게 하기
- 델리게이트는 두 개의 메서드를 사용해서 사용자가 특정행을 선택했는지 알 수 있다.
그 중 한 개가 행이 선택되기 전에 호출되고 이 매서드에서 행이 선택되는 것을 막거나 심지어 선택되는 행을 바꿀 수도 있다.
-(NSIndexPath *)tableView:(NSTableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
// 선택하려는 항목이 첫번째이라면 nil 을 리턴하여 선택하지 못하게 한다.
if(row == 0)
return nil;
return indexPath;
}
* 선택한 특정 행 알아내기
// 이 메서드는 실제 선택을 다룬다
// 사용자가 행을 골랐을 때 적절한 동작을 수행하는 곳이며, 선택했을 때 안내 메시지 창을 띄운다.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
NSString *rowValue = [listData objectaAtIndex:row];
NSString *message = [[NSString alloc] initWithFormat:@"You selected %@", rowValue];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Row Selected" message:message delegate:nil cancelButtonTitle:@"Yes I Dis" otherButtonTitles:nil];
[alert show];
[message release];
[alert relase];
/*
선택한 행과 다른 행이나 영역을 선택하는 효과가 있는 인덱스패스(indexPath)를 바꿀 수 있다.
아래 행을 주석 처리하면 경고 메시지 창이 뜨고 확인 후 선택되어 있는 행을 볼 수 있지만
주석을 풀면 선택된 행은 없어진다.
*/
[tableView deselectRowAtIndexPath:IndexPath animated:YES];
}
* 폰트 크기 바꾸기
cell.TextLabel.font = [UIFont boldSystemFontOfSize:50];
* 델리게이트에서 테이블 높이 지정
// 테이블 행의 높이를 지정하는 델리게이트
// 필요하다면 각각의 행마다 고유의 값을 지정할 수도 있다.
-(CGFolat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70;
}
* 맞춤형 테이블 뷰 만들기
- UITableViewCell 이 지원하는 방식이 아닌 다른 방식
UITableViewCell 에 하위 뷰를 추가 하는 것.
UITableViewCell 의 하위 클래스를 만드는 것
UITableViewCell 에 하위 뷰를 추가 하는 방식
-(UITablveViewCell *)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];
CGRect nameLabelRect = CGRectMake(0,5,70,15);
UILabel *nameLabel = [[UILabel alloc] initWithFrame:nameLabelRect];
nameLabel.textAlignment = UITextAlignmentRight;
nameLabel.text = @"Name";
nameLabel.font = [UIFont boldSystemFontOfSize:12];
[cell.contentView addSubview:nameLabel];
[nameLabel release];
CGRect colorLabelRect = CGRectMake(0,26,70,15);
UILabel *colorLabel = [[UILable alloc] initWithFrame:colorLabelRect];
colorLabel.textAlignment = UITextAlignmentRight;
colorLabel.text = @"Color";
colorLabel.font = [UIFont boldSystemFontOfSize:12];
[cell.contentView addSubview:colorLabel];
[colorLabel release];
CGRect nameValueRect = CGRectMake(80,5,200,15);
UILabel *nameValue = [[UILabe alloc] initWithFrame:nameValueRect];
nameValue.tag = kNameValueTag; //나중에 해당 레이블에게 값을 할당할 수 있도록 이 필드를 찾을 방법을 추가
[cell.contentView addSubview:nameValue];
[nameValue release];
CGRect colorValueRect = CGRectMake(80,25,200,15);
UILabel *colorValue = [[UILabel alloc] initWithFrame:colorValueRect];
colorValue.tag = kColorValueTag; // 나중에 해당 레이블에게 값을 할당할 수 있도록 이 필드를 찾을 방법을 추가
[cell.contentView addSubview:colorValue];
[colorValue release];
}
NSUInteger row = [indexPath row];
NSDictionary *rowData = [self.computers objectAtIndex:row];
UILabel *name = (UILabel *)[cell.contentView viewWithTag:kNameValueTag]; // 해당 레이블 찾기
name.text = [rowData objectForKey:@"Name"];
UILabel *color = (UILabel *)[cell.contentView viewWithTag:kColorValueTag]; // 해당 레이블 찾기
color.text = [rowData objectForKey:@"Color"];
return cell;
}
UITableViewCell 의 하위 클래스 만들어 사용하기
- 인터페이스 빌더를 사용해서 테이블 셀 뷰를 설계하기
- UITableViewCell 의 하위 클래스와 테이블 뷰 셀을 담을 새 nib 파일을 만든다.
그런 후에 테이블 뷰 셀이 행을 표현할 때 테이블 뷰 셀에 하위 뷰를 추가하는 대신에 단순히 nib 파일에서
구현한 하위 클래스를 로드하고 두 개의 새 아웃렛을 사용해서 이름과 색을 결정할 것.
1. Xcode 에서 class 폴더에 Cocoa Touch Classes 를 고르고 Objective-C class 를 선택한다.
하위 클래스로 UITableViewCell 을 선택하고 새로운 파일을 추가한다.
파일명은 "CustomCell"으로 하고 Also create 가 선택되었는지 확인.
2. Xcode 에서 resources 폴더에 User Interfaces 를 클릭하고 Empty XIB 을 추가한다.
파일명은 "CustomCell".
3. CustomCell.h 파일에 아래 코드를 추가
#import <UIKit/UIKit.h>
@interface CustomCell : UITableViewCell
{
UILabel *nameLabel;
UILabel *colorLabel;
}
@property (nonatomic, retain) IBOutlet UILabel *nameLabel;
@property (nonatomic, retain) IBOutlet UILabel *colorLabel;
@end
4. CustomCell.m 파일에 추가
@synthesize nameLabel;
@synthesize colorLabel;
-(void)dealloc {
[nameLabel release];
[colorLabel release];
[super dealloc];
}
5. CustomCell.xib 을 더블클릭해서 인터페이스 빌더를 연다.
- Table View Cell 을 라이브러리에서 찾아서 nib 메인 윈도우에 끌어 놓는다.
- 테이블 뷰 셀을 선택했는지 확인하고 아이덴티티 인스펙터를 띄우고 ClassIdentify 에서 Class 를 CustomCell 로 변경.
- View size 에서 높이를 65 로 변경
- Table View Cell 에서 Identifier 를 CustomCellIdentifier 로 변경
- 라이브러리에서 view 를 찾아서 Custom cell 윈도우를 추가한다.
- View 크기를 x 를 0 , y 를 0 , w 를 320 , h 를 65 로 변경
- 라이브러리에서 Label 을 4개 추가하여 위치를 맞추고 모양을 결정한다.
- Custom Cell 아이콘에서 드래드 해서 nameLabel 과 colorLabel 을 아웃렛에 할당한다.
- 이 테이블 셀은 데이터를 보여주기 위해서 사용하지만 사용자와의 상호작용은 테이블 뷰가 수행하므로
독자적인 컨트롤러 클래스가 필요없다.
6. 새 테이블 뷰 셀 사용하기
#import "CustomCell.h"
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CustomCellIdentifier = @"CustomCellIdentifier";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CustomCellIdentifier];
if(cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
for(id oneObject in nib)
if([oneObject isKindOfClass:[CustomCell class]])
cell = (CustomCell *)oneObject;
}
NSUInteger row = [indexPath row];
NSDictionary *rowData = [self.computers objectAtIndex:row];
cell.colorLabel.text = [rowData objectForKey:@"color"];
cell.nameLabel.text = [rowData objectForKey:@"Name"];
return cell;
}
7. 이 델리게이트 메서드는 셀이 생기기 전에 호출돼서 필요한 값을 셀에서 얻지 못하므로 그 값을 하드코딩해야 한다.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 66;
}
* 그룹으로 묶은 섹션과 인덱스로 구분한 섹션
- 인터페이스 빌더에서 추가한 TableView 에서 Table View Style 을 Grouped 로 변경한다.
### SectionsViewController.h ####
#import <UIKit/UIKit.h>
@interface SectionsViewController:UIViewController <UITableViewDelegate, UITableViewDataSource>
{
NSDictionary *names;
NSArray *keys;
}
@property (nonatomic, retain) NSDictionary *names;
@property (nonatomic, retain) NSArray *keys;
@end
### SectionsViewController.m ####
#import "SectionViewController.h"
@implementation SectionsViewController
@synthesize names;
@synthesize keys;
-(void)viewDidLoad
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"sortednames" ofType:@"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.names = dict;
[dict release];
NSArray *array = [[names allKeys] sortedArrayUsingSelector:@selector(compare:)];
self.keys = array;
}
-(void)viewDidUnload
{
self.names = nil;
self.keys = nil;
}
-(void)delloc
{
[names release];
[keys release];
[super delloc];
}
#pragma mark -
#pragma mark Table View Data Source Methods
// 세션의 갯수가 몇개인지를 리턴한다.
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [keys count];
}
// 특정 섹션의 행의 갯수가 몇개인지를 리턴한다.
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
return [nameSection count];
}
// 테이블 셀 생성
// indexPath에서 section과 row를 뽑아서 딕셔너리의 어떤 값에 해당하는지 찾을때 이용한다.
// section을 사용해서 names Dictionary에서 어떤 배열을 가져올지 알수 잇고 그래서 row를 그 배열에서 어떤 값을 이용할지 알아내는 데 사용할수 있다.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectAtIndex:key];
static NSString *SelectionsTableIdentifier = @"SelectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SelectionsTableIdentifier];
if(cell == nil)
{
cell = [[[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SelectionsTableIdentifier] autorelease];
}
cell.textLabel.text = [nameSection objectAtIndex:row];
return cell;
}
// 각 섹션의 헤더 값을 설정할수 있다.
-(NSString *)viewTable:(UIViewTable *)viewTable titleForHeaderInSection:(NSInteger)section
{
NSString *key = [keys objectAtIndex:section];
return key;
}
// 다음 메서드를 추가해서 Table View style이 Plain (인덱스 정렬)일 경우 Index를 추가 할수 있다.
-(NSArray *)sectionIndexForTitlesTableview:(UITableView *)tableView
{
return keys;
}
* 검색 창 구현하기
- 디자인 다시 생각하기
--- 델리케이트와 데이터소스는 수정 가능한 딕셔너리에서 읽고 검색 기준이 바뀌거나 검색을 취소하면 수정 가능한 딕셔너리를 수정 불가능한 딕셔너리의 내용으로 고치면 될듯
* 깊은 뮤터블 복사
- NSDictionary는 NSMutableDictionary 프로토콜을 따르기 때문에 얕은 복사본인 NSMutableDictionary를 리턴한다. 이말은 mutableCopy 메서드를 호출 했을때 원래 딕셔너리가 가진 객체 모두를 가지는 새 NSMutableDictionary 객체를 만드는것을 위미한다.
- 얕은 복사는 해당 메모리 영역을 가리키는 주소 값만을 복사하는것을 의미한다. 보통 얇은 복사를 하게 되면 한 메모리 영역을 두 개의 포인터가 가리키게 되므로, 한쪽에서 할당된 메모리를 해제하면 다른 한쪽에서 사용할 수 있는 메모리 영역을 잃게 되는것이다.
- 깊은 복사는 메모리 영역 전체를 별도로 복사하는것을 의미한다.
* 카테고리 사용
- 카테고리를 사용하면 하위클래스를 만들지 않고 이미 존재하는 객체에 메서드를 추가할 수 있다.
### NSDictionary-MutableDeepCopy.h ####
#import <foundation foundation.h="">
@interface NSDictionary (MutableDeepCopy)
-(NSMutableDictionary *)mutableDeepCopy
@end
</foundation>
### SectionsViewController.h ###
'개발 > App Developer' 카테고리의 다른 글
멀티뷰 애플리케이션 (0) | 2010.08.30 |
---|---|
탭바와 피커 (0) | 2010.08.30 |
리눅스 쬐금 (0) | 2010.08.30 |
tableView 의 클래스와 프로토콜 이해 (0) | 2010.08.29 |
UITableViewDataSource 프로토콜의 주요 메서드 (0) | 2010.08.29 |