깔끔한 Table View 코드
UITableViewController vs. UIViewController
Apple는 테이블뷰스 전속의view controller 클래스로 UItable ViewController를 제공합니다.Table view controllers는 융통성이 없는 코드를 반복해서 쓰는 것을 피할 수 있도록 아주 유용한 기능을 실현했습니다.그나저나 테이블 뷰 컨트롤러는 전체 화면에 전시된 테이블 뷰만 관리할 수 있다.대부분의 경우, 이것이 당신이 원하는 것이지만, 그렇지 않으면, 다음에 우리가 보여준 것처럼 이 문제를 해결할 다른 방법이 있다.
Table View Controllers의 특징
Table view controllers는 Table view를 처음 표시할 때 데이터를 불러옵니다.또한 테이블 뷰의 편집 모드, 키보드 알림에 응답, 그리고 옆에 있는 슬라이딩 알림을 표시하고 선택한 배경색을 지우는 작은 작업도 도와줍니다.이러한 특성을 적용하기 위해서, 하위 클래스에viewWillAppear:나viewDidAppear: 같은 이벤트 방법을 덮어쓸 때 슈퍼 버전을 호출해야 합니다.
Table view controllers는 표준view controllers에 비해 애플이 실현하는 '밑줄 리셋' 을 지원한다.현재 문서에서 유일하게 UIrefresh Control을 사용하는 방법은 테이블 뷰 컨트롤러입니다. 다른 곳에서도 작업을 할 수 있도록 노력하지만 다음 iOS가 업데이트될 때는 안 될 가능성이 높습니다.
이러한 요소를 합치면 대부분의 애플이 정의한 표준 테이블 뷰 상호작용 행위를 제공합니다. 만약 이 기준에 부합된다면, 테이블 뷰 컨트롤러를 직접 사용해서 융통성이 없는 코드를 쓰지 않도록 하는 것이 좋습니다.
Table View Controllers 제한 사항
Table view controllers의view 속성은 항상 테이블 뷰입니다.만약 당신이 잠시 후에 테이블 뷰 옆에 뭔가를 표시하기로 결정한다면 (예를 들어 지도), 이상한 hacks에 의존하지 않는다면 어쩔 수 없을 것입니다.
만약 당신이 코드를 사용한다면.xib 파일로 정의된 인터페이스입니다. 표준view controller로 이동하는 것은 매우 간단합니다.하지만storyboards를 사용한다면 이 과정은 몇 가지 절차를 더 포함해야 한다.다시 만들지 않으면storyboards에서tableview controller를 표준view controller로 바꿀 수 없습니다.이것은 모든 내용을 새view controller로 복사한 다음 다시 연결해야 한다는 것을 의미합니다.
마지막으로, 이전한 후에 잃어버린 테이블 뷰 컨트롤러의 기능을 보충해야 합니다.대부분viewWillAppear:또는viewDidAppear:의 간단한 문장입니다.편집 모드를 전환하려면 테이블 뷰의 편집 속성을 전환하는 action 방법이 필요합니다.대부분의 작업은 키보드를 다시 만드는 지원에서 나온다.
이 길을 선택하기 전에 우리가 관심을 가져야 할 기능(관심점 분리)을 분리함으로써 추가 혜택을 얻을 수 있는 더 쉬운 선택이 있다.
Child View Controllers 사용
tableview controller를 완전히 버리는 것과 달리,childview controller로 다른view controller에 추가할 수도 있습니다. (이 화제에 대한 글)이렇게 하면parent view controller는 다른 당신이 필요로 하는 새로운 인터페이스 요소를 관리하는 동시에 테이블 view controller는 테이블view를 계속 관리할 수 있습니다 -(void)addPhotoDetailsTableView { DetailsViewController *details = [[DetailsViewController alloc] init]; details.photo = self.photo; details.delegate = self; [self addChildViewController:details]; CGRect frame = self.view.bounds; frame.origin.y = 110; details.view.frame = frame; [self.view addSubview:details.view]; [details didMoveToParentViewController:self]; } 만약 이 해결 방안을 사용한다면,childview controller와parentview controller 사이에 메시지 전달 경로를 만들어야 합니다.예를 들어, 사용자가 테이블 뷰에 있는cell을 선택했다면,parent view controller는 이 이벤트를 알고 다른view controller로 밀어넣어야 합니다.사용 습관에 따라 일반적으로 가장 뚜렷한 방법은 이 테이블뷰 컨트롤러에 delegate protocol을 정의한 다음parent view 컨트롤러에 가서 실현하는 것입니다.
@protocol DetailsViewControllerDelegate
- (void)didSelectPhotoAttributeWithKey:(NSString *)key;
@end
@interface PhotoViewController ()
@end
@implementation PhotoViewController
// ...
- (void)didSelectPhotoAttributeWithKey:(NSString *)key
{
DetailViewController *controller = [[DetailViewController alloc] init];
controller.key = key;
[self.navigationController pushViewController:controller animated:YES];
}
@end
보시다시피 이러한 구조는view controller 간의 메시지 전달에 추가 비용을 가져왔지만, 보답으로 코드의 봉인과 분리가 매우 뚜렷하고 더욱 좋은 복용성을 가진다.실제 상황에 따라 일을 더욱 간단하게 할 수도 있고 복잡하게 할 수도 있기 때문에 독자가 스스로 고려하고 결정해야 한다.
관심 분야 분리(Separating Concerns)
테이블 뷰어를 처리할 때 모델스, controllers,views 사이를 오가는 다양한 임무가 있습니다.view controllers가 모든 일을 하는 것을 피하기 위해서, 우리는 가능한 한 이 임무들을 적당한 곳으로 나누어, 이렇게 하면 읽기, 유지보수, 테스트에 유리하게 할 것이다.
여기에 기술된 기술은 문장의 더 가벼운 View Controllers의 개념의 연장이다. 이 문장을 참고하여 데이터 소스와 모델의 논리를 재구성하는 방법을 이해하십시오.table views와 결합하여view controllers와views 사이에서 관심사를 어떻게 분리하는지 구체적으로 봅시다.
Model 객체와 Cells 사이의 가교 구축
때때로 우리는 표시하고 싶은 모델층의 데이터를view층에 전송해서 표시해야 한다.모델과view 사이를 명확하게 분리하기를 원하기 때문에그래서 보통 이 임무를 테이블 뷰의 데이터 소스에 옮겨서 처리한다. - (UItable View Cell *) 테이블 뷰: (UItable View *) 테이블 뷰 cell ForRow AtIndex Path: (NSIndex Path *) indexPath {PhotoCell *cell = [table View dequeue Reue Reusable Cell With Identififier::@ PhotoCell] Photo Photo 포토 = [Photo phot 포토 = [Intex selite = [Intex selitex sel indem: Pathell, Pathbel Pottex Photex Photex indededet = 포토.name; NSString date =[self.dateFormatter stringFromDate:photo.creationDate]; cell.photoDateLabel.text = date; } 그러나 이런 코드는 데이터 소스를 혼란스럽게 할 수 있다. 왜냐하면 데이터 소스에cell의 디자인을 폭로했기 때문이다.가장 좋은 것은 분해해서cell류의 category에 넣는 것이다.
@implementation PhotoCell (ConfigureForPhoto)
- (void)configureForPhoto:(Photo *)photo
{
self.photoTitleLabel.text = photo.name;
NSString* date = [self.dateFormatter stringFromDate:photo.creationDate];
self.photoDateLabel.text = date;
}
@end
상술한 코드가 생기면 우리의 데이터 소스 방법은 간단해진다.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
PhotoCell *cell = [tableView dequeueReusableCellWithIdentifier:PhotoCellIdentifier];
[cell configureForPhoto:[self itemAtIndexPath:indexPath]];
return cell;
}
우리의 예시 코드에서,tableview의 데이터 소스는 단독 클래스로 분해되었고,cell을 설정한 Block으로 초기화됩니다.이때, 이 Block은 이렇게 간단해졌다.
TableViewCellConfigureBlock block = ^(PhotoCell *cell, Photo *photo) {
[cell configureForPhoto:photo];
};
Cells 재사용 가능
때때로 여러 모델의 대상은 같은 유형의cell로 표시해야 한다. 이런 상황에서 우리는cell을 다시 사용할 수 있도록 할 수 있다.우선, 우리는cell에protocol을 정의합니다. 이cell로 표시되는 대상은 반드시 이protocol을 따라야 합니다.그리고 이 프로토콜을 따르는 모든 대상을 받아들일 수 있도록category의 설정 방법을 간단하게 수정합니다.이러한 간단한 절차는cell과 그 어떠한 특수한 모델 대상 사이를 결합시켜 서로 다른 데이터 형식에 적응할 수 있도록 한다.
Cell 내부에서 Cell 상태 제어
테이블뷰스의 기본 하이라이트나 선택 행동을 사용자 정의하려면 두 가지delegate 방법을 사용해서 클릭한cell을 우리가 원하는 모양으로 수정할 수 있습니다.예를 들면 다음과 같습니다.
- (void)tableView:(UITableView *)tableView
didHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
PhotoCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.photoTitleLabel.shadowColor = [UIColor darkGrayColor];
cell.photoTitleLabel.shadowOffset = CGSizeMake(3, 3);
}
- (void)tableView:(UITableView *)tableView
didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
PhotoCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.photoTitleLabel.shadowColor = nil;
}
그러나 이 두 가지 delegate 방법의 실현은view controller를 바탕으로cell 실현의 구체적인 세부 사항을 알 수 있다.만약에cell을 바꾸거나 다시 설계하려면delegate 코드를 고쳐야 합니다.View의 구현 디테일과delegate의 구현이 교차되었다.우리는 반드시 이 세부 사항들을cell 자체로 옮겨야 한다.
@implementation PhotoCell
// ...
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
[super setHighlighted:highlighted animated:animated];
if (highlighted) {
self.photoTitleLabel.shadowColor = [UIColor darkGrayColor];
self.photoTitleLabel.shadowOffset = CGSizeMake(3, 3);
} else {
self.photoTitleLabel.shadowColor = nil;
}
}
@end
전반적으로 말하자면view층과 controller층의 실현 세부 사항을 분리하려고 노력하고 있다.delegate는view가 어떤 상태를 보여야 하는지 분명히 알아야 하지만,view 구조를 어떻게 수정하거나 어떤subviews에 어떤 속성을 설정해서 정확한 상태를 얻을 수 있는지 알아야 한다.모든 논리는view 내부로 봉인된 다음 외부에 간단한 API를 제공해야 합니다.
여러 셀 유형 제어
만약 테이블 뷰에 여러 종류의cell이 있다면 데이터 소스 방법은 곧 제어하기 어려울 것이다.우리의 예시 프로그램에서 포토 details table에는 두 가지 종류의cell이 있습니다. 하나는 몇 개의 별을 표시하는 데 사용되고, 다른 하나는 키 값을 표시하는 데 사용됩니다.서로 다른cell 유형의 코드를 구분 처리하기 위해 데이터 소스 방법은 간단하게cell의 유형을 판단하여 임무를 다른 지정한 방법에 보냅니다.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *key = self.keys[(NSUInteger) indexPath.row];
id value = [self.photo valueForKey:key];
UITableViewCell *cell;
if ([key isEqual:PhotoRatingKey]) {
cell = [self cellForRating:value indexPath:indexPath];
} else {
cell = [self detailCellForKey:key value:value];
}
return cell;
}
- (RatingCell *)cellForRating:(NSNumber *)rating
indexPath:(NSIndexPath *)indexPath
{
// ...
}
- (UITableViewCell *)detailCellForKey:(NSString *)key
value:(id)value
{
// ...
}
Table View 편집
Table view는 cell을 삭제하거나 다시 정렬할 수 있는 사용하기 쉬운 편집 기능을 제공합니다.이 이벤트들은 테이블 뷰의 데이터 소스가delegate 방법을 통해 알림을 받을 수 있습니다.따라서, 보통 우리는delegate 방법에서 데이터에 대한 수정 작업을 볼 수 있다.
데이터를 수정하는 것은 모델층에 속하는 작업이 분명하다.Model은 삭제나 재배열 같은 작업에 API를 노출한 다음 데이터 소스 방법에서 호출할 수 있습니다.이렇게 하면 controller는view와 모델 간의 조율자 역할을 할 수 있으며 모델층의 실현 세부 사항을 알 필요가 없다.또한 모델의 논리도 더 쉽게 테스트할 수 있습니다.view controllers의 작업과 섞이지 않기 때문입니다.
총결산
Table view controllers(및 기타 controller 대상!)모델과view 대상 사이에서 조정자와 조정자의 역할을 해야 합니다.이것은view층이나 모델층에 뚜렷하게 속하는 작업에 관심을 가져서는 안 된다.delegate와 데이터 소스 방법이 더 작아지고 간단한 샘플 코드를 포함할 수 있다는 점을 항상 기억해야 한다.
이것은 테이블 뷰 controllers와 같은 크기와 복잡성을 줄일 뿐만 아니라, 업무 논리와view의 논리를 더욱 적합한 곳에 두었다.Controller층의 안팎의 실현 디테일은 모두 간단한 API로 봉인되어 최종적으로 더욱 쉽게 이해되고 팀워크에 유리하게 되었다.
ObjC 중국
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.