지난 포스팅에서는 JSON 디코딩을 지원하는 타입을 만들어 보았습니다. 이번에는 디코딩된 JSON 데이터를 활용해서 Table View를 만들어보겠습니다!
먼저 스토리보드에서 View Controller에 Table View를 올려 놓습니다.

화면에서 Table View가 존재할 위치를 잡습니다.

Table View Cell을 Table View 위에 올려둡니다.

Cell을 선택(클릭)해서 Attributes Inspector의 Reuse Identifier의 이름을 설정해줍니다.

Cocoa Touch Class 형식으로 UIViewController 타입을 가진 파일을 하나 만듭니다. 초기 View Controller를 Table View로 만들고 싶을 경우에는 새로 만들지 않고 기존 파일을 활용하셔도 됩니다.

생성한 ViewController에 JSON 데이터를 디코딩하기 위한 코드를 추가합니다. Table View를 연결할 IBOutlet도 함께 만들어줄게요.
class ViewController: UIViewController {
  // MARK: - Properties
  @IBOutlet private weak var tableView: UITableView!
  private var artworks: [Artwork] = []
  
  // MARK: - View life cycle
    override func viewDidLoad() {
      super.viewDidLoad()
      let decodedResult: Result = ExpoJSONDecoder.decode(to: [Artwork].self,from: ExpoData.artworks)
      
      switch decodedResult {
      case .success(let result):
        artworks = result
      case .failure(let error):
        debugPrint(error)
      }
    }
}
그리고 스토리보드에서 미리 만들어둔 View Controller의 Identity Inspector의 Class란에 새로 만든 View Controller의 이름을 작성합니다.

Connections Inspector으로 이동해서 만들어준 IBOutlet과 UI 요소로 만들어둔 Table View를 이어줍니다.

여기에서 tableView의 Cell에 들어갈 내용이 Basic, Right Detail 등 기본적으로 제공되는 스타일로 커버가 가능한 경우는 해당 스타일을 이용하시면 됩니다. 하지만 저처럼 그림과 제목, 짧은 설명과 이동 아이콘까지 여러 내용을 Cell에 넣고 싶으시다면 UI 요소를 활용해 직접 Cell을 디자인해보세요.


직접 Custom Cell을 만들어주신 경우, Cocoa Touch Class 형식으로 UITableViewCell 타입을 가진 파일을 하나 만들고, 데이터를 넣어줄 요소들을 IBOutlet으로 정의한 다음 스토리보드에서 Cell의 Custom Class를 지정해주고, 각 IBOutlet을 UI 요소와 연결해주세요.
import UIKit
class ArtworkTableViewCell: UITableViewCell {
  @IBOutlet weak var thumbnailImageView: UIImageView!
  @IBOutlet weak var titleLabel: UILabel!
  @IBOutlet weak var shortDescriptionLabel: UILabel!
}


계속해서 TableView와 함께 일해줄 delegate와 dataSource를 지정해주어야 하는데요, 사전 작업으로 UITableViewDelegate와 UITableViewDataSource 프로토콜을 채택해주고 각 프로토콜의 요구사항을 충족시켜주어야 해요.

요구사항을 보니 UITableViewDataSource 프로토콜에 optional로 표기되지 않은 두 가지 메서드를 구체화해주는 것이네요.
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    code
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    code
  }
첫 번째 메서드는 tableView(_:numbersOfRowsInSection:)로, 한 섹션에 몇 개의 열(Row)가 들어갈 것인가를 알려주는 메서드에요. 두 번째 메서드인 tableView(_:cellForRowAt:)은 tableView의 각 열에 들어갈 셀(Cell)의 데이터를 채워 UITableViewCell 타입으로 반환하는 메서드입니다. 작성된 코드를 보시면 어떤 내용인지 바로 이해가 되실거에요.
// MARK: - Table view data source
extension ViewController: UITableViewDataSource {
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return artworks.count // 디코딩된 데이터의 배열 요소 갯수를 열 개수로 반환
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    // Reuseable Cell 선언
    let cell: ArtworkTableViewCell = tableView.dequeueReusableCell(
      withIdentifier: "artworkCell",
      for: indexPath
    ) as! ArtworkTableViewCell 
    
    // Reuseable Cell에 데이터 할당
    cell.thumbnailImageView.image = UIImage(named: artworks[indexPath.row].imageName)
    cell.titleLabel.text = artworks[indexPath.row].name
    cell.shortDescriptionLabel.text = artworks[indexPath.row].shortDescription
    
    return cell
  }
}
이전 포스팅에서 다룬 적이 있지만 delegate는 Table View 대신에 스크롤링 지원을 위해 셀의 높이를 계산한다든지 셀이 선택되는 등 테이블과의 상호작용을 다루어주고, dataSource는 테이블에 데이터와 셀을 제공하는 역할을 수행합니다. 이 친구들은 두 가지 방법으로 지정해줄 수 있어요. 둘 중에 하나만 하셔도 됩니다.
Table View를 구현하고자하는 View Controller에 아래와 같은 코드를 작성합니다.override func viewDidLoad() {
  super.viewDidLoad()
  tableView.delegate = self
  tableView.dataSource = self
}
Connections inspector 탭에서 dataSource와 delegate를 View Controller에 연결합니다.
이제 오토 레이아웃을 조금 적용해주면 아래와 같은 화면을 확인하실 수 있습니다. 세부 화면으로 이동할 때 데이터를 이동시키는 등 세부 화면으로의 이동 방법은 다음 포스팅에서 다루도록 하겠습니다~!
