OverView
Android 에서는 ListView는 iOS Legacy UI 에서는 TableView 로 불리고 SwiftUI에서는 List로 불린다. 이 List Widget 혹은 List Object, List Library, List View & Controls 는 다음과 같은 Creation Route 를 가진다.
[기초] TableView 만들기 (Objective-C + Xib)
테이블 뷰는 데이터 소스를 가져와서 한 줄 씩 화면에 뿌려 주는 객체(Object)이다. 또 데이터 소스를 표현하는 줄(Row)이 길어져서 화면을 넘어가면 자동으로 스크롤바가 붙는다. 라이브러리에서 (⌘⇧L 라이브러리 열기 단축키) 테이블 뷰를 Xib에 D&D(Drag & Drop) 한다.
한 화면에 3개의 테이블 뷰를 배치하면 스토리보드(Storyboard, Xib)에서 다음과 같이 표현된다.
원하는 모양으로 화면 구성(뒤에서는 스토리 보드 작성이라고 말한다)을 한다.
화면 구성 후에는 테이블 세팅을 위해 UIViewController<UITableViewDelegate, UITableViewDataSource> 를 상속 받아 구현해 주어야 한다.
Table 의 섹션 개수를 반환한다.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
1로 적으면 1개의 섹션이다. 거의 대부분의 테이블은 지속적으로 데이터가 추가되기 때문에 섹션 구분을 하지 않고 보통 1로 두며, 다른 섹션의 경우 별도의 테이블로 만들어 같은 화면에 표시한다.
Table 의 Row 개수를 반환 한다.
- (NSInteger) tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
return [mList count];
}
table을 몇 줄로 할 것인지 미리 정한다. 보통 한 파일 내에서 멤버 배열(mList)로 두고 해당 배열의 크기를 row 개수로 정한다.
Table 의 Cell 을 채운다.
하나의 Row를 Cell이라고 한다.
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (cell == nil) {
cell = ...
}
return cell;
}
요약하면, Table View 에서는 Cell 의 개수 먼저 정하고 Cell 을 만드는 것이 중요하다.
코드로 셀을 추가하는 방법
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
셀을 코드로 만들어 주면 된다.
TIP! : legacy code의 경우, 셀을 코드로 추가한 셀이 복잡한 UI인 경우 refresh 할 때 문제가 된다.
if( cell != nil ) {
for(int i=0; i<[cell.contentView.subviews count];i++)
if([cell.contentView.subviews objectAtIndex:i] != nil)
[[cell.contentView.subviews objectAtIndex:i] removeFromSuperview];
}
와 같이 수동으로 삭제한 후 다시 그려주어야 한다.
테이블 셀 클래스 정의
테이블 뷰를 추가 했었던 스토리 보드의 오브젝트 리스트를 보면 Table View 아래 Table View Cell이 있다.
Table View Cell 을 Table View 위로 D&D 한 후. Cell 내부 구성 요소를 만들 수 있다.. 이 후, 셀을 위한 클래스 생성하고 해당 클래스에 셀 내부 구성 요소를 연결 한다.
import UIKit class DragonballCell : UITableViewCell { @IBOutlet weak var lbMain: UILabel! @IBOutlet weak var lbSub: UILabel! override func awakeFromNib() { super.awakeFromNib() // Initialization code } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state } } |
만들어진 셀은 테이블 뷰의 cellForRowAt 에서 원하는 소스를 세팅 한다.
let cell: DragonBallCell cell = (tableView.dequeueReusableCell (withIdentifier: "DragonballCell") as? DragonballCell)! cell.lbMain.text = "mainText" cell.lbSub.text = "subText" return cell |
[실전] sqlite DB와 TableView 연동하기
onClickCheckingCategory onClickSerarchingCategory onClickDownloadSite |
NSMutableArray *tCheck = [NSMutableArray arrayWithCapacity:0]; SqlUtils *db = [[SqlUtils alloc] init]; [db selectAll_SITE_TPPG_LOC:tCheck]; if([tCheck count] < 1) { [GlobalVar alertMsgOKWithTitle:@"mBASS" message:@"현장 정보 자료 받기를 먼저 해 주세요."]; } else { CheckingCategory *v = [[CheckingCategory alloc] initWithNibName:@"CheckingCategory" bundle:[NSBundle mainBundle]]; self.title = @""; [self.navigationController pushViewController:v animated:YES]; GlobalVar.globalVar.globalcounterofstack4frontview++; } |
View를 만든다.
HoldPointView.xib
#ifndef HoldPointView_h #define HoldPointView_h @interface HoldPointView : UIViewController { } @end #endif /* HoldPointView_h */ |
#import "HoldPointView.h" @implementation HoldPointView @end |
@property (weak, nonatomic) IBOutlet UITableView *mTableView; |
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the "HoldPointView" nib but the view outlet was not set.' terminating with uncaught exception of type NSException |
#import "HoldPointView.h" @implementation HoldPointView -(void) viewDidLoad { [super viewDidLoad]; self.mTableView.dataSource = self; self.mTableView.delegate= self; [self.mTableView reloadData]; } #pragma mark - #pragma mark === TableView DataSource === - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 1; } - (NSInteger) tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section { return 5; } #pragma mark - #pragma mark TableView Delegate - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { |
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *vCell = @"Cell4Default"; UITableViewCell *cell = nil; cell = [tableView dequeueReusableCellWithIdentifier:vCell]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:vCell]; UILabel *vLabel = [[UILabel alloc] initWithFrame:CGRectMake(6, 2, 90, 30)]; vLabel.textAlignment = UITextAlignmentCenter; vLabel.text = @"cell"; vLabel.textColor = [UIColor blueColor]; vLabel.backgroundColor = [ UIColor clearColor]; vLabel.font = [UIFont systemFontOfSize:14]; [vLabel setAdjustsFontSizeToFitWidth:YES]; [vLabel setTag:1]; [cell.contentView addSubview:vLabel]; } return cell; } |
@interface HoldPointView : UIViewController <UITableViewDelegate, UITableViewDataSource> { NSMutableArray *mList; } |
- (void) selectTable_DDTBT_HPTYPE:(NSMutableArray *)array isAll:(BOOL)isAll { NSLog(@"SQLUTILS_selectDong"); [array removeAllObjects]; [self checkBackDB]; if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) { NSString *query = @"select ID_CHK_TYPE \ ,NM_CHK_TYPE \ from DDTBT_HPTYPE;"; NSLog(@"Query = %@", query ); const char *sqlStatement = [query cStringUsingEncoding:NSASCIIStringEncoding]; sqlite3_stmt *compiledStatement; if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) { while(sqlite3_step(compiledStatement) == SQLITE_ROW) { DDTBT_HPTYPE *data = [[DDTBT_HPTYPE alloc] init]; data.ID_CHK_TYPE = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)]; data.NM_CHK_TYPE = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)]; [array addObject:data]; } } sqlite3_finalize(compiledStatement); } sqlite3_close(database); } |
-(void) viewDidLoad { [super viewDidLoad]; if (nil == mList) mList = [NSMutableArray arrayWithCapacity:0]; SqlUtils *db = [[SqlUtils alloc] init]; [db selectTable_DDTBT_HPTYPE:mList isAll:YES]; self.mTableView.dataSource = self; self.mTableView.delegate= self; [self.mTableView reloadData]; } |
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *vCell = @"Cell4Default"; NSUInteger row = [indexPath row]; UITableViewCell *cell = nil; cell = [tableView dequeueReusableCellWithIdentifier:vCell]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:vCell]; UILabel *vLabel = [[UILabel alloc] initWithFrame:CGRectMake(6, 2, 90, 30)]; vLabel.textAlignment = UITextAlignmentCenter; DDTBT_HPTYPE *vHP = [mList objectAtIndex:row]; vLabel.text = vHP.NM_CHK_TYPE; vLabel.textColor = [UIColor blueColor]; vLabel.backgroundColor = [ UIColor clearColor]; vLabel.font = [UIFont systemFontOfSize:14]; [vLabel setAdjustsFontSizeToFitWidth:YES]; [vLabel setTag:1]; [cell.contentView addSubview:vLabel]; } return cell; } |
if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:vCell]; UIImage *imageUp = [UIImage imageNamed:@"btn_check_o.png"]; UIImage *imageDn = [UIImage imageNamed:@"btn_check_d.png"]; UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)]; [btn addTarget:self action:@selector(onClickCheck:) forControlEvents:UIControlEventTouchUpInside]; [btn setImage:imageUp forState:UIControlStateNormal]; [btn setImage:imageDn forState:UIControlStateSelected]; [btn setImageEdgeInsets:UIEdgeInsetsMake(4, 6, 4, 2)]; [btn setTag:0]; [cell.contentView addSubview:btn]; UILabel *vLabel = [[UILabel alloc] initWithFrame:CGRectMake(6, 2, 90, 30)]; vLabel.textAlignment = UITextAlignmentCenter; DDTBT_HPTYPE *vHP = [mList objectAtIndex:row]; vLabel.text = vHP.NM_CHK_TYPE; vLabel.textColor = [UIColor blueColor]; vLabel.backgroundColor = [ UIColor clearColor]; vLabel.font = [UIFont systemFontOfSize:14]; [vLabel setAdjustsFontSizeToFitWidth:YES]; [vLabel setTag:1]; [cell.contentView addSubview:vLabel]; } |
@interface DDTBT_HPTYPE : NSObject { NSString *ID_CHK_TYPE; NSString *NM_CHK_TYPE; BOOL isCheck; } @property (nonatomic, strong) NSString *ID_CHK_TYPE; @property (nonatomic, strong) NSString *NM_CHK_TYPE; @property (nonatomic, assign) BOOL isCheck; - (void)clear; |
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *vCell = @"Cell4Default"; NSUInteger row = [indexPath row]; UITableViewCell *cell = nil; cell = [tableView dequeueReusableCellWithIdentifier:vCell]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:vCell]; UIImage *imageUp = [UIImage imageNamed:@"hp_yesorno.png"]; UIImage *imageDn = [UIImage imageNamed:@"hp_yes.png"]; UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 15, 22, 22)]; [btn addTarget:self action:@selector(onClickCheck:) forControlEvents:UIControlEventTouchUpInside]; [btn setImage:imageUp forState:UIControlStateNormal]; [btn setImage:imageDn forState:UIControlStateSelected]; [btn setImageEdgeInsets:UIEdgeInsetsMake(4, 6, 4, 2)]; [btn setTag:0]; [cell.contentView addSubview:btn]; UILabel *vLabel = [[UILabel alloc] initWithFrame:CGRectMake(40, 12, 120, 26)]; vLabel.textAlignment = UITextAlignmentCenter; DDTBT_HPTYPE *vHP = [mList objectAtIndex:row]; vLabel.text = vHP.NM_CHK_TYPE; vLabel.textColor = [UIColor blackColor]; vLabel.backgroundColor = [ UIColor clearColor]; vLabel.font = [UIFont systemFontOfSize:18]; [vLabel setAdjustsFontSizeToFitWidth:YES]; [vLabel setTag:1]; [cell.contentView addSubview:vLabel]; } else { [((UIButton*)cell.contentView.subviews.firstObject) setSelected:((DDTBT_HPTYPE *)[mList objectAtIndex:row]).isCheck]; } return cell; } |
- (void)onClickCheck:(id)sender { // 선택한 로우가 몇번째인지 UITableViewCell *cell; UITableView *tv; cell = (UITableViewCell*)[[sender superview] superview]; tv = (UITableView*)cell.superview; NSIndexPath *path=[tv indexPathForCell:cell]; NSLog(@"clickCheck4 in BsVrfChkInfoDwIdList"); BOOL chk = NO; DDTBT_HPTYPE *data2 = nil; BOOL ret = NO; for (int i=0; i<[mList count]; i++) { data2 = [mList objectAtIndex:i]; data2.isCheck = NO; } [_mTableView reloadData]; DDTBT_HPTYPE *data = [mList objectAtIndex:path.row]; data.isCheck = YES; chk = data.isCheck; UIButton *btn = sender; [btn setSelected:chk]; } |
'C++' 카테고리의 다른 글
잘 되던게, 갑자기 안되는 문제 해결. (0) | 2021.05.20 |
---|---|
ImageButton (0) | 2021.05.18 |
UIViewController 중첩 (0) | 2021.05.18 |
SOAP protocol (0) | 2021.05.18 |
자주 쓰는 팝업 구현방법, 그리고 데이터 넘기기 (0) | 2021.05.18 |
최근댓글