[ swift ] 키오스크 과제 tableView 1차

sonny·2024년 11월 26일
7

TIL

목록 보기
53/133
post-thumbnail

내가 구현해야 하는 부분은 하단 tableView 이다.


더미 데이터 지정

우선 임의로 더미 데이터를 배열로 구성했다.
그리고 MenuDataViewController class를 보면 3개의 프로토콜을 채택한 것이 보인다.

공부할겸 다시 각각에 대해 정리를 했다.

이 부분이 중요했던 게 ..

나는 이걸 공부했는데 delegate 또는 dataSource를 설정하지 않으면

테이블 뷰가 데이터를 표시하지 않는다는걸 까먹고 채택하지않아 왜 뷰가 안나오나 했었기 때문.....

코드 실행 전에 delegatedataSource를 반드시 설정해야 한다는 점을 확인하고,

덕분에 tableView와 관련된 프로퍼티를 viewDidLoad에서만 초기화하는 것을 다시 점검했다.


1. UIViewController

UIViewController는 화면을 관리하는 뷰 컨트롤러 클래스다.

이 클래스를 상속받으면 화면을 구성하고, UI의 동작을 처리할 수 있다.

UIViewController를 상속하는 이유는 이 클래스가 화면과 관련된 여러 작업을 처리할 수 있게 해주기 때문인데,

예를 들어 화면 전환, 뷰 초기화, 사용자 입력 처리 등을 할 수 있다는 것이다.

2. UITableViewDelegate

UITableViewDelegateUITableView 의 동작을 제어하는 데 필요한 메서드를 정의하는 프로토콜이다.

이 프로토콜을 채택하면 테이블 뷰의 행 선택, 셀의 높이 조정, 셀의 표시 방식 등을 제어할 수 있다.

이 프로토콜을 채택하는 이유는 테이블 뷰에서 사용자와의 상호작용을 다루기 위해서인데,

예를 들면 사용자가 셀을 선택했을 때 어떤 동작을 할지 결정하거나, 셀의 높이를 동적으로 설정할 수 있게 한다.

3. UITableViewDataSource

UITableViewDataSourceUITableView에 데이터를 공급하는 역할을 하는 프로토콜이다.

이 프로토콜을 채택하면 테이블 뷰에 표시할 데이터를 제공할 수 있다.

UITableViewDataSource 프로토콜을 채택하는 이유는 테이블 뷰의 행 수나 각 셀의 데이터를 제공해야 하기 때문이다.

이 프로토콜은 필수적인 메서드들을 정의하면서 데이터를 어떻게 테이블 뷰에 전달할지를 결정한다.

결론적으로 3개의 프로토콜을 채택한 이유는

MenuDataViewController 클래스에서 테이블 뷰를 사용하고,

테이블 뷰의 동작과 데이터 제공을 모두 처리해야 하기 때문이라고 볼 수 있겠다.

  • UITableViewDataSource는 테이블 뷰의 데이터 소스를 담당하고,

  • UITableViewDelegate는 테이블 뷰의 동작을 제어하며,

  • UIViewController는 화면을 관리하는 기본 클래스로, 이 세 가지 역할을 하나의 클래스에서 처리할 수 있게 된다.

그러니 테이블 뷰를 사용할 때 데이터 제공과 동작을 처리하려면

UITableViewDataSourceUITableViewDelegate를 채택하고,

기본적으로 화면을 관리하려면 UIViewController를 상속해야 한다는 점을 기억하자.


viewDidLoad() 메서드

viewDidLoad() 메서드는 뷰 컨트롤러의 뷰가 로드된 후에 호출되는 메서드이다.

이 메서드에서 화면의 초기 설정과 레이아웃을 정의한다.

코드를 보면 우선 백그라운드 컬러는 ligthGray 색상으로 해주고,

view.addSubview(tableView)는 테이블 뷰를 화면에 추가하는 코드다.

tableView는 앞에 내가 정의한 테이블 뷰의 객체인데,

addSubview() 메서드를 사용해 현재 뷰에 추가된다.

그리고 tableView.delegate = selftableView.dataSource = self

테이블 뷰의 동작을 설정하기 위해 필수로 해야 하는 코드다.

이걸 설정하지 않으면 테이블 뷰가 데이터를 어떻게 표시할지 그리고

사용자와 상호작용을 어떻게 처리할지 알 수 없기 때문이다.

이 부분은 테이블 뷰 셀을 재사용하기 위해 등록하는 코드인데,

register() 메서드를 사용해서 MenuTableViewCell 클래스를 MenuCell이라는 셀 식별자와 함께 등록한다.

이 식별자는 테이블 뷰가 셀을 재사용할 때 사용된다.


register 메서드

register 메서드는 Xcode에서 제공하는 UITableView의 메서드인데, 테이블 뷰에 셀을 등록하는 역할을 한다.

이 메서드는 재사용 가능한 셀을 등록할 때 사용되는데,

테이블 뷰가 데이터를 표시할 때 해당 셀을 효율적으로 재사용할 수 있도록 해준다고 알고있으면 된다.


셀 높이 고정 및 레아이웃 설정

tableView.rowHeight = 90
tableView.snp.makeConstraints { make in
     make.leading.trailing.equalToSuperview()
     make.bottom.equalToSuperview()
     make.top.equalToSuperview().offset(450) 
}   

그리고 tableView.rowHeight = 90는 각 테이블 뷰 셀의 고정 높이를 설정하는 코드인데,

여기서는 각 셀의 높이를 90으로 지정했다.

tableView.snp.makeConstraints { make in ... } 이건 스냄킷을 사용해서 테이블 뷰의 레이아웃을 설정하는 부분인데,

make.leading.trailing.equalToSuperview() 는 좌우 끝이 부모 뷰에 맞춰지도록 했다.

make.bottom.equalToSuperview()는 하단이 부모 뷰에 맞춰지도록 하고,

make.top.equalToSuperview().offset(450) 는 상단이 부모 뷰에서 450만큼 떨어지도록 설정했다.

동적인 높이 계획을 위해.

이후 테이블 뷰의 크기를 동적으로 조정할 계획이 있기 때문에

동적인 높이 조정을 시도할 수 있도록

make.height.equalTo(tableView.contentSize.height) 코드도 주석으로 남겼다.

그리고 top.offset(450) 은 특정 상단 여백을 강제로 설정했기 때문에, 다른 화면 크기나 환경에서는 UI가 어색해질 수 있지만,

이 부분은 디바이스 크기와 상관없이 자동으로 맞춰지는 레이아웃을 구성하기 위해 safeAreatopLayoutGuide를 사용하는 방안을 고려 중이다.

다른 팀원과 파일을 합칠 때 바로 사용이 되길 바란다... 제발 ㅎㅎ

tableView.reloadData()

이건 테이블 뷰의 데이터를 다시 로드하는 메서드인데,

이 메서드는 테이블 뷰가 화면에 표시되기 전에 데이터가 변경되었거나 업데이트가 필요할 때 사용된다.

데이터를 다시 로드하면 테이블 뷰가 갱신되어 새로운 데이터가 반영된다.

이거 안했다고 계속 햄버거 셀을 모두 삭제하면 튕기는 현상이 있었는데 이 코드가 해결해줬다.


UITableView의 데이터 소스 메서드

아래 코드는 테이블 뷰에 표시할 셀의 수와 각 셀의 내용을 정의해주는 코드인데,

이 메서드는 테이블 뷰에게 각 섹션에 몇 개의 행 (row) 이 있어야 하는지 알려준다.

section이 테이블 뷰의 섹션을 나타내는 파라미터고,
(여기서는 하나의 섹션만 사용하고 있다.)

return dummyBurgers.count는 dummyBurgers 배열의 개수만큼 행(row)을 생성하도록 설정해준다.

dummyBurgers가 10개의 햄버거데이터를 가지고 있다면,

테이블 뷰는 10개의 셀을 표시하게 된다는 것.

위 코드의 역할은 테이블 뷰에게 특정 위치(indexPath)에 표시할 셀을 반환하고,

셀을 재사용 큐에서 가져오거나 새로운 셀을 생성해 반환해주는 역할이다.

자세히 보자면,

dequeueReusableCell(withIdentifier:for:) 는 테이블 뷰의 재사용 큐에서 셀을 가져오는 메서드다.

그리고 "MenuCell"의 경우 셀을 등록할 때 사용한 식별자(reuseIdentifier) 라고 한다.

이 식별자를 통해 특정 셀을 가져올 수 있다는 점!

indexPath는 셀의 위치를 나타내는 값으로 sectionrow를 포함하고,

as? MenuTableViewCellMenuTableViewCell 타입으로 셀을 캐스팅한다는 코드다.

만약 캐스팅에 실패하면 기본 UITableViewCell 을 반환하여 안전성을 확보해줘야한다.

그리고 indexPath.row는 현재 행(row)의 인덱스를 나타내는 것인데,

dummyBurgers[indexPath.row]dummyBurgers 배열에서 해당 인덱스에 해당하는 데이터를 가져온다.

이제 첫 번째 행에서는 dummyBurgers[0]이 반환되고,

두 번째 행에서는 dummyBurgers[1]이 반환된다.

요약 하자면,,

numberOfRowsInSection은 테이블 뷰에 몇 개의 행(row)을 표시할지 정의해주는 거고,

cellForRowAt은 각 행에 표시할 데이터를 설정하고 재사용 가능한 셀을 반환하는 것,

그리고 여기서는 dummyBurgers 배열의 데이터를 사용해 각 셀의 데이터를 채운다는 것.


음....

기억에 남는게 numberOfRowsInSectioncellForRowAt 메서드를 통해 데이터를 테이블 뷰와 연결해주면서

뭔가 테이블 뷰의 동작 방식을 좀더 명확히 이해할 수 있던 시간이었다.

cellForRowAt에서 셀을 재사용하는건 효율성 면에서도 중요한 부분이긴 했는데,

이 과정에서 데이터와 UI가 자연스럽게 연결된다는 점을 또 한번 깨달았다.

특히, 커스텀 셀(MenuTableViewCell)을 캐스팅하고 데이터를 바인딩하면서 뷰와 데이터를 연결하는 과정이 걱정과 다르게 잘 된 것 같아서 뿌듯하다.

그리고 단순한 구조처럼 보이지만 delegate, dataSource, 그리고 레이아웃 설정 등 세부적인 부분까지 신경 써야 제대로 동작한다는 것도 다시금 깨달았고...

테이블 뷰는 기본이지만 강력하다는걸 실감한 날이다.

다음 이어서 또 작성해보겠다.

profile
iOS 좋아. swift 좋아.

1개의 댓글

comment-user-thumbnail
2024년 11월 26일

compose랑 비슷해서 흥미롭네요

답글 달기

관련 채용 정보