본문 바로가기

프로그래밍/iOS,macOS

UITableView / UICollectionView


기본 프로토콜

<UITableViewDelegate,UITableViewDataSource>



필수메쏘드

* static UITableView의 경우 인스턴스가 미리 생성되어있으므로, 아래 루틴은 필요 없게 된다.



// 전체 열의 갯수(섹션별)

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

{

return 0;

}


// indexPath에 해당하는 UITableViewCell

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

{

// tableview cell 객체를 얻거나 생성해 리턴해 줘야한다.

// 셀식별용 문자열

// static NSString *cellIdentifier=@"cell";



// 재사용가능한 셀 얻는 방식으로 재사용 가능한 셀이 없을 경우 nil을 리턴한다.

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"셀식별자"];


if(cell == nil) {

cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"셀식별자"];

}



// cell 데이터 처리

// indexPath를 사용해 실제 데이터의 index를 가져와 UI 컨트롤에 데이터를 설정한다.

// 라벨, 이미지 등등

// 비동기 처리등도 이곳에 추가한다.

NSInteger row = [indexPath row];

cell.label.text = [myList objectAtIndex:row];

.

.

.


return cell;

}




각 셀의 높이값 지정(optional)

-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath

{

if( indexPath.row == 0 ) {

return 100;

}


return [super tableView:tableView heightForRowAtIndexPath:indexPath];

}





별도의 xib 셀 생성하기

UITableViewCell을 상속받은 커스텀셀 클래스 생성.

xib를 생성해 table view cell 추가 후 커스텀셀 클래스 연결. 

속성에서 identifier 설정한다.

인터페이스 빌더에서 생성하지 않으면 코드상에서 셀 생성한뒤 identifier를 넣어주어야 한다.

identifier가 정의되지 않으면 dequeue 시에 nil값이 항상 리턴되어, 계속 셀을 만들게 된다.


nib파일 등록

dequeueReusableCellWithIdentifier: forIndexPath: 를 사용하기 위해서는 nib와 identifier가 등록되어야 한다.


UITableViewController 에서 뷰 생성 시점(viewDidLoad 등) 에 nib에 대한 identifier를 정의한다.

[tableView registerNib:[UINib nibWithNibName:@"nib이름" bundle:nil] forCellWithReuseIdentifier:@"셀식별자"];




UITableViewController에서 프로토콜 구현

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

{

// 기본방식이나 indexPath를 넣는 방식으로 셀을 얻어온다.
// 1. 기본방식
CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:@"셀식별자"];

if(cell == nil) {
// 등록된 nib 에서 셀을 찾을 수 없는 경우 해당 이름의 xib파일에서 셀 얻기
NSArray *nibs=[[NSBundle mainBundle] loadNibNamed:@"xib_file_name" owner:self options:nil];

// 해당하는 xib 찾아 생성
for( id nib in nibs) {
if( [nib isKindOfClass:[CustomCell class]]) {
cell = (CustomCell *)nib;
break;
}
}
}

// 2. indexPath를 사용한 방식

// indexPath를 사용한 셀 얻기 : 이방식은 항상 유효한 셀을 리턴하게 된다.

// 자동으로 nib로 셀을 생성해 주기 때문에 nib 파일이 셀식별자와 함께 등록되어 있어야 한다.

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"셀식별자"

forIndexPath:indexPath];



// cell 데이터 처리

// 라벨, 이미지 등등

// 비동기 처리등도 이곳에 추가한다.

.

.

.


return cell;
}








셀 데이터 처리

이미지등 데이터를 네트워크를 통해 읽어오는 경우 비동기 처리를 하게되는데,

이경우 설정하기 전에 테이블뷰의 현재 indexPath가 사용가능한지 파악해야 한다.

UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]


이미지 비동기 처리 예)

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{

NSURL *url = [NSURL URLWithString:(@"http://url/image.png")];

NSData *data = [NSData dataWithContentsOfURL:url];

UIImage *image = [UIImage imageWithData: data];


dispatch_async(dispatch_get_main_queue(), ^{

CustomCell *cell = (CustomCell*)[tableView cellForRowAtIndexPath:indexPath];

if( cell != nil ) {

cell.imageView.image = image;

}

});


});




셀의 사이즈 및 레이아웃 관련 사항만 다시그리기

사이즈 변경등으로 셀의 내부 컨텐츠는 건드리지 않고, 셀을 다시 그린다.

내부에 뷰들이 포함될 경우 reload 를 하면 깜박임이 발생하는데, 이경우는 자연스럽게 셀의 모양만 조정된다.

[self.tableView beginUpdates];

[self.tableView endUpdates];





SubView에 맞게 동적으로 늘어나는 Cell


-(void)viewDidLoad에 테이블뷰의 셀 높이의 기본값과 자동계산됨을 설정한다.

self.tableView.estimatedRowHeight = 50;

self.tableView.rowHeight = UITableViewAutomaticDimension;



셀 높이를 반환하는 메쏘드에도 동일한 값을 리턴하도록 한다.

-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath

{

return UITableViewAutomaticDimension;

}



동적으로 맞출 View는 -(CGSize)intrinsicContentSize 메쏘드를 제공해야 한다.

UILabel, UIButton, UIImageView 등은 현재 데이터에 따라 intrinsic size을 갱신하고, 위 메쏘드를 통해 사이즈 정보를 반환한다. 커스텀뷰도 이런 컨트롤과 같이 동작하도록 위 메쏘드에서 높이를 계산해 리턴해 주면 된다.

제약조건에 width , height 와 같은 고정된 값이 있는 정적인 구조라면 상하좌우 제약만 추가해주면 자동으로 사이즈가 계산된다.

단 인터페이스 빌더가 셀 크기와 맞지 않는다고 에러를 낼 수 있으니 bottom 의 경우 >= 0 과 같이 잡아주면 인터페이스 빌더에서는 에러를 없애고 런타임시에도 정상 적용된다.


인터페이스 빌더로 디자인 시에 높이나 너비를 확정할 수 없다면, 해당 커스텀 뷰를 셀의 Content View에 넣을때 constraint를 top, leading, bottom, trailing 잡아주고, intrinsicContentSize 를 제공해 줘야 한다.


자동으로 맞추는 높이를 다시 수동으로 임의 조정하는 경우(셀 숨기기 처럼 셀 높이를 0으로 만드는 등) 셀의 프레임 사이즈가 변경되어 기존 제약 조건들과 충돌이 일어나고, 에러 로그가 출력된다.

이경우 bottom 에 연결된 제약조건의 우선순위를 낮춰 주면 해결된다.




내부 크기 변환 등 처리 후 셀내부의 변화가 일어나 크기가 변화 했으니 다시 그리라고 알린다.

[self invalidateIntrinsicContentSize];

[self.tableView beginUpdates];

[self.tableView endUpdates];




* 이것저것


테이블뷰가 보여질때 상단에 마진이 생기는 경우가 있다.

스토리보드에서 뷰컨트롤러의 속성에서 Adjust scroll view insets 을 체크해제하면 된다.









UICollectionView

테이블과 거의 같은데, cell 이외에 supplementary 라는 뷰를 포함할 수 있다.

UICollectionViewLayout 을 통해 스크롤 방향이나 배치를 조정할 수 있다.

UICollection Reusable View 는 헤더나 푸터

UICollection View Cell 은 각 아이템을 나타낸다.


IB에서 Collection View 추가 하고, 내부에 Collection View Cell 추가 한다.

Collection View Cell 의 reusable 을 위해 identifier를 정의


프로토콜

<UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout>



셀얻기

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView 

cellForItemAtIndexPath:(NSIndexPath*) indexPath

{

UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"셀식별자"

forIndexPath:indexPath];


// cell에 데이터 설정


return cell;

}



데이터추가/삭제

데이터 배열에 데이터 추가한뒤 해당 데이터의 indexPath를 얻어서 넣어준다.

NSIndexPath *indexPath = [NSIndexPath indexPathForItem:[_dataList[0] count]-1 inSection:0];

[self.collectionView insertItemsAtIndexPaths:@[indexPath]];



삭제시에는 삭제할 NSArray 를 전달해 주면 된다.

[self.collectionView deleteItemsAtIndexPaths:selectedList];





'프로그래밍 > iOS,macOS' 카테고리의 다른 글

오토레이아웃 이것저것 / Constraint / UITextView  (0) 2016.10.25
커스텀객체와 인터페이스빌더  (0) 2016.10.23
스토리보드 / XIB  (0) 2016.10.22
싱글톤  (0) 2016.10.19
코어 데이터 정리  (0) 2016.10.18
슬라이드메뉴  (0) 2016.10.16
파일 가져오기  (0) 2016.10.16
뷰 에니메이션  (0) 2016.10.13
비동기 처리 ( GCD , NSOperation )  (0) 2016.10.13
[objective-c] 블록구문  (0) 2016.10.13