본문 바로가기
개발(Development)/iOS(아이폰)

[한글 번역_08] Start Developing iOS Apps (Swift) - Working with Table Views > Create a Table View

by 카레유 2015. 10. 30.
안녕하세요 카레유입니다.

Apple에서 제공해주는 Swift iOS 앱 개발 가이드를 한글 번역해보았습니다.

영어실력도, 개발실력도, 심지어 한국어 실력도 미흡합니다.

부족한 부분이 많지만, 많은 도움 되시길 바라겠습니다.

아직 작성 중인 내용으로 시간을 갖고 개선해 나갈 생각입니다.

감사합니다.



Create a Table View

이번 레슨에서는 FoodTracker 앱의 메인 화면을 만들어보겠습니다. 음식의 목록을 보여주기 위해 테이블뷰(Table View)기반의 화면을 만들어 스토리보드에 추가할 것이며, 각 음식의 목록은 아래 화면과 같이 커스텀 테이블 셀(table cell)을 만들어 구현하겠습니다.

image

Learning Objectives

At the end of the lesson, you’ll be able to:

  • 스토리보드에 두 번째 scene 생성하기

  • 테이블 뷰의 기본 구성요소 이해하기

  • 커스텀 테이블뷰 셀을 만들고 디자인 하기

  • TableViewDelegate와 Data Source의 역할 이해하기

  • 배열에 데이터를 저장하고 작업하기

  • 테이블 뷰에 동적인 데이터 표시하기

Create the Opening Scene

현재 FoodTracker앱은 하나의 scene과 view controller를 통해 음식의 이름과 사진, 그리고 별점평가를 보여주는 음식의 상세화면을 구현하고 있습니다. 이제 모든 음식의 목록을 보여주기 위한 리스트 화면을 만들어야 할 때입니다. 다행히도 iOS는 UITableView라고 하는 아주 강력한 내장 클래스를 제공합니다. 이 클래스를 이용하면 아이템의 목록을 노출하는 화면을 쉽게 구현할 수 있으며 스크롤 기능도 기본으로 제공합니다.

테이블뷰(table view)는 UITableViewController의 객체인 tableViewController를 통해 관리됩니다. UITableViewController는 테이블뷰와 관련된 로직을 수행하는되 최적화된 클래스로 UIViewController의 서브클래스입니다. 이제 table view controller에 기반한 새로운 화면(scene)을 만들어보겠습니다.

To add a scene with a table view to your storyboard

  1. Main.Stroyboard를 선택해서 스토리보드를 열어주세요

  2. utility area에서 Object library를 열어주세요 (Veiw > Utitlites > Show Object Library를 클릭하면 나옵니다)

  3. Object library에서 Table View Controller객체를 찾으세요

  4. Table View Controller를 드래그해서 canvas의 기존 scene(Meal scene)의 왼쪽에 배치시키세요 

    혹시 컨텐츠가 있는 table view만 보이고, 아무런 것도 발생하지 않는다면, table view를 드래그하신 겁니다. table view가 아니라 table view controller를 드래그 해야합니다. table view는 table view controller에 의해 관리되는 여러 요소들 중 하나에 불과합니다. 모든 패키지를 사용하기 위해서는 table view controller를 드래그 하여 사용해야 합니다.

이제 스토리보드에 두개의 화면(scene)이 생겼습니다. 새로 만든 것은 음식 목록을 보여줄 화면이며, 기존에 있던 화면은 음식을 추가하기 위한 화면입니다.

앱을 실행 시켰을 때 나오는 첫 화면은 음식 목록 화면으로 하겠습니다. 따라서 table view controller를 첫 번째 화면(scene)으로 지정해야합니다.

To set the table view controller as the initial scene

  1. 좀더 넓게 작업을 하려면 아래 처럼 툴바를 조정하여 proeject navigator와 utility area를 축소시켜주세요

    image

    outline view도 숨길 수 있겠지요

  2. meal scene에 있는 "스토리보드 시작점(storyboard entry point)"을 드래그해서 table view controller로 옮기세요 

    image

    스토리보드에서 table view controller를 첫화면(initial view controller)으로 설정하였습니다. 이제 앱이 실행되면 이 화면이 가장 먼저 실행됩니다.

    image

Checkpoint: 앱을 실행해보세요! text field, image view, rating control이 있는 meal scene이 아니라 빈 table view가 보일거에요. 수많은 행이 있지만 컨텐츠는 비어있겠지요

image

약간의 세팅작업을 통해 이 table view를 앱에서 사용할 수 있게 만들어봅시다.

To configure the table view

  1. 스토리보드에서 outline view를 열어주세요

  2. outline view에서 Table View를 선택하세요.

    table view는 "Scene > TableViewController > TableView"에 속해있습니다. 이런 관계를 보기 위해선 outline view에서 각 객체들 왼쪽의 삼각형을 누르면 알 수 있어요

    image
  3. table view가 선택된 상태에서 uitility area의 Size inspector를 열어주세요. 

    스토리보드에 있는 객체들의 사이즈나 위치즐 조정하기 위한 영역입니다.

    image
  4. Row Height 필드의 값을 90으로 입력하고, 리턴키를 누르세요.

    각 행의 높이가 90으로 변경됩니다.

다른 작업을 하게에 앞서, 먼저 table view에서 보여줄 cell에 대한 인터페이스를 디자인하고 나서, table view자체에 대한 작업을 진행해보겠습니다.

Design Custom Table Cells

테이블 뷰의 각 행(row)들은 UITableViewCell 객체인 table view cell에 의해 관리 됩니다. table view cell을 통해 컨텐츠를 구성하여 각 행(row)에 노출하게 됩니다. table view cell은 다양한 셀 스타일과 내장기능을 갖고 있습니다. 디폴트 스타일만으로도 멋진 셀을 만들 수 있지만, 그 이상의 컨텐츠를 표시하기 위해서는 커스텀 셀 스타일을 직접 정의해서 사용해야합니다.

To create a subclass of UITableViewCell

  1. Command-N을 누르세요(File > New > File 로 들어가도 됩니다)

  2. 다이얼로그 왼쪽에서 iOS를 선택하세요

  3. 오른쪽에서 Cocoa Touch Class를 선택하고 Next를 클릭하세요

  4. Class 필드에 Meal이라고 입력하세요

  5.  Subclass of 필드에서 UITableViewCell을 선택하세요

    class의 이름이 MealTableViewCell로 변경될 것입니다. Xcode가 적절한 이름을 만들어 준것으로, 그냥 두세요

  6. Langugae 옵션은 Swift로 해주세요

  7. Next를 클릭하세요

    저장경로는 프로젝트 디렉토리가 디폴트로, group옵션은 app이름인 FoodTracker가 디폴트로, Target은 App은 선택되어있고, Tests는 선택되어있지 않을 것입니다.

  8. 이 디폴트 상태를 그대로 두고 Create를 클릭하세요. 

    MealTableViewCell클래스가 정의된 MealTableViewCell.swift파일이 생성될 것입니다.

이제 스토리 보드를 열어주세요

스토리보드에 table view controller의 scene이 나타나며, 현재는 하나의 셀(cell)만 표시됩니다.

image

이 셀은 다른 모든 셀들을 대표하는 일종의 프로토타입입니다. 이 셀에 적용된 디자인과 작동방식이 테이블뷰(table view)내의 모든 셀에 동일하게 적용됩니다. 이 작업을 위해서는 먼저 프로토타입 셀을 방금전에 생성한 커스텀 테이블뷰 셀 클래스로 연결해야합니다.

To configure a custom cell for your table view

  1. outline view에서 Table View Cell을 선택해주세요. 

    table view의 왼쪽 삼각형을 눌러 펼쳐보면 보일 것입니다.

    image
  2. table view cell이 선택된 상태에서 utitliy area의 Attributes inspector을 열어주세요

  3. Atributes inspector에서 "Identifier"필드에 "MealTableViewCell" 이라고 입력하고 엔터키를 눌러주세요. 

    나중에 보겠지만 이 작업은 정말 중요한 과정입니다.

  4. Attributes inspector의 Selection 필드에서 None를 선택해주세요. 

    이 옵션을 선택하면, 사용자가 셀을 탭했을 때, 아무런 하이라이트 표시도 하지 않습니다.

  5. Size inspector를 열어주세요

  6. Size inspector에서 Row Height 필드에 93을 입력해주세요. 

    바로 오른쪽에 있는 Custom 체크박스가 체크되어 있는지 확인해주세요

    직접 만든 커스텀 테이블 뷰 셀을 사용하겠다는 의미입니다.

    image

    리턴키를 눌러주세요. 스토리보드 상에서 셀의 높이가 설정한대로 적용됩니다.

  7. Identity inspector를 열어주세요. 

    Identity inspector에서는 스토리보드에 있는 객체가 어느 클래스에 속하는지 등 identity 관련된 속성을 편집할 수 있습니다.

  8. Identity inspector의 Class필드에서 MealTableViewCell을 선택해주세요

    image

cell에 대한 설정을 완료한 상태에서, 스토리보드에서 아래와 같이 음식의 name, photo, rating을 추가하는 custom UI디자인을 하면 됩니다

image

이 작업을 위해서는 label, image view, rating control이 필요합니다. rating control은 이전에 작업한 내용을 재활용하겠습니다.

To design the interface of the custom table cell

  1. 메뉴바에서 "Editor > Canvas > Show Boudns Rectangles" 를 선택해서 UI에서 엘리먼트 들의 경계선이 표시되게 하세요. table view cell에 엘리먼트들을 배치하기가 더 편합니다.

    image
  2. Object library에서 Image View 객체를 드래그해서 tabe view cell에 놓으세요

  3. 사이즈를 잘 조정해서 상하좌우 경계까지 꽉 채우세요

    image
  4. 이전 레슨에서 디폴트 이미지를 추가하지 않았다면 지금 추가해두세요

  5. image view가 선택된 상태에서 uitility area의 Attribute inspector를 열어주세요

  6. Attributes inspector를 열고 image필드에서 "defaultPhoto"를 선택해주세요

    image
  7. Object library에서 Label을 드래그하여 table view cell에 추가해주세요

  8. 드래그 해서 image view 오른쪽에 위치시키고, table cell의 상단 마진에 맞추어주세요

    image
  9. 라벨의 가로 길이를 조정해서 table cell의 오른쪽 마진까지 늘려주세요

    image
  10. Object library 에서 View 객체를 드래그해서 table cell에 두세요

  11. 추가한 view를 선택한 상태에서 utitlity area 에서 Size inspector를 열어주세요

  12. Size inspector에서 Height 필드 값은 44,  Width 값은 240을 입력하고 리턴키를 눌러주세요

  13. view를 드래그해서 label 아래에 위치시키고 label과 왼쪽 경계가 맞게 정렬해주세요

    image
  14. view가 선택된 상태에서 Indetity inspector를 열어주세요

  15. Identity inspector에서 Class 필드의 값을 RatingControl로 선택해주세요

    image

    혹시 팝업메뉴에서 RatingControl이 보이지 않는다면, view객체가 선택된 상태인지 확인해보세요

  16. view가 선택된 상태에서 Attributes inpector를 열어주세요

  17. Attributes inpector 에서 Interaction필드의 User Interaction 항목을 체크 해제 해주세요

    RatingControl 클래스는 사용자의 반응에 동작하게 설계가 되어있긴 하지만, table view cell에서는 단순히 보여주기만 해야합니다.따라서 User Interaction항목은 해제해야 합니다.

지금까지 작업한 화면은 아래와 같습니다.

image

Checkpoint: 앱을 실행시켜보세요. table view cell이 좀더 길어진 것을 확인 할 수 있습니다. 그런데 table view cell에 UI엘리먼트를 넣어놨는데 왜 보이지 않을까요?

image

스토리보드에서 table view는 정적 데이터(static data : 스토리보드에서 삽입한 데이터)나 동적 데이터(dynamic data :  TableViewController의 로직에 의해 제공되는 데이터)를 노출하게 설정할 수 있습니다. table view는 디폴트로 동적 데이터를 사용하게 설정되어있습니다. 그래서 스토리보드에 우리가 작업한 정적 데이터가 앱을 실행해도 보이질 않는 것이지요. 즉, 코드상에서 데이터 모델을 구현하여 로딩한 데이터를 table view에 노출시키는 작업을 해야합니다. 

지금은 assistant editor를 이용해 UI를 미리 확인하는 작업만 해보겠습니다.

To preview your interface

  1. 툴바에서 Assistant editor를 열어주세요 

    image
  2. 작업공간이 부족하다면 project navigator와 utilty area를 숨겨주세요

    image

    outline view도 숨기셔도 됩니다.

  3.  editor selector bar에서 Automatinc 을 클릭하고 Preview > Main.storyboard(Preview)를 클릭하세요

    image

    Xcode윈도우가 아래 화면처럼 보일거에요

    image

preview상에서 작업한 대로 UI가 표시되는 것을 확인할 수 있습니다.  tabe view cell 프로토타입의 UI작업은 끝났습니다.

Add Images to Your Project

다음으로 샘플 이미지 들을 프로젝트에 추가하겠습니다. 앱을 처음 실행할 때 노출할 이미지로 사용할 예정입니다.

샘플 이미지는 다운로드한 소스의 Images/폴더에서 찾을 수 있습니다.

To add images to your project

  1. assistant editro가 열려있다면 standard editor로 돌아오세요. 

    project navigator와 utility area도 다시 열어주세요

    image
  2. project navigator에서 Images.xcassets를 선태해서 asset catalog를 열어주세요. 

    asset catalog는 앱에서 사용할 이미지를 저장하고 관리하는 곳입니다.

  3. 왼쪽 아래에 있는 플러스(+)버튼을 누르면 나오는 팝업 메뉴에서 New Folder를 클릭하세요

  4. 폴더 이름 부분을 더블클릭해서 "Sample Images"로 이름을 바꾸어주세요

  5. 폴더가 선택된 상태에서 왼쪽 아래의 플러스(+)버튼을 누르면 나오는 팝업 메뉴에서 New Image Set을 클릭하세요

  6. image set의 이름 부분을 더블클릭해서 나중에 코드를 작성할 때 기억하기 쉬운 이름으로 바꾸어주세요

    레슨에서는 meal1 형태로 이름을 지었습니다

  7. 컴퓨터의 파인더에서 추가할 이미지를 선택하세요

  8. 그 이미지를 드래그 해서 image set의 2x슬롯에 넣으세요

5~8번의 과정을 추가할 이미지들에 대해서 모두 반복 작업해주세요. 레슨에서는 3개의 이미지가 있다고 가정하고 진행하겠습니다.

image

Connect the Table Cell UI to Code

테이블 뷰 셀(table view cell)에 동적인 데이터를 노출하기 위해서는 스토리보드 상에서 테이블뷰 셀을 구성하고 있는 각 뷰 객체들을 MealTableViewCell.swift에서 참조할 수 있도록 outlet 연결을 만들어야 합니다.

To connect the views to the MealTableViewCell.swift code

  1. 스토리보드에서 table view cell에 있는 Label을 선택해주세요

  2. 툴바에서 assistant editor를 열어주세요

    image
  3. 작업공간이 부족하다면 툴바에서 project navigator와 utility area를 숨겨주세요

    image
  4. editor selector area에서 Automatic > MealTableViewCell.swift를 클릭하세요

    image

    MealTableViewCell.swift 파일이 오른쪽 에디터에 나타납니다.

  5. 아래와 같은 클래스 선언부를 찾으세요

    1. class MealTableViewCell: UITableViewCell {
  6. 클래스 구현부에 아래 주석을 추가하세요

    1. // MARK: Properties
  7. 스토리보드의 Label을 control을 누른 상태에서 드래그하여 MealTableViewCell의 주석 밑으로 연결하세요

    image
  8. 다이얼로그가 나타나면 Name필드에 "nameLabel"이라고 입력하세요

    나머지 옵션은 아래와 같이 그대로 두세요

    image
  9. Connect를 클릭하세요

  10. 스토리보드의 테이블뷰 셀에서 이미지뷰를 선택하세요

  11. control을 누른 채 드래그하여 nameLabel 프로퍼티 밑으로 연결해주세요

    image
  12. In the dialog that appears, for Name, type photoImageView. 다이얼로그가 나타나면 Name필드의 값을 "photoImageView"로 입력하세요

    나머지 옵션을 그대로 두고 Connect를 클릭하세요

    image
  13. 스토리보드에서 테이블 뷰 셀의 rating control을 선택해주세요

  14. control을 누른채 드래그하여 photoImageView프로퍼티 밑으로 연결하세요

    image
  15. 다이얼로그가 나타나면 Name필드에 "ratingControl"이라고 입력하세요

    나머지 옵션은 그대로 두고 Connect를 클릭하세요

    image

MealTableViewCell.swift 파일에 아래와 같은 outlet이 생성되었습니다. 이 outlet들을 통해 테이블 뷰 셀의 각 뷰 객체를 참조하여 사용할 수 있습니다.

  1. @IBOutlet weak var nameLabel: UILabel!
  2. @IBOutlet weak var photoImageView: UIImageView!
  3. @IBOutlet weak var ratingControl: RatingControl!

Load Initial Data

테이블 뷰 셀에 실제로 데이터를 노출하기 위해서는 해당 데이터를 로드하는 코드를 작성해야합니다. 이를 위해 음식(meal)에 대한 데이터 모델(data model)인 Meal클래스를 작성해 두었습니다. Meal클래스의 객체 하나가 음식 하나를 의미한다고 볼 수 있습니다. 음식 객체들의 리스트도 관리해야 하는데, 음식 리스트 화면(scene)을 관리하는 커스텀 뷰 컨트롤러가 이 역할을 하기에 적합합니다. 뷰 컨트롤러 상에 데이터 모델에 대한 참조체를 만들고, 이를 통해 음식 목록을 노출하는 화면을 구현하면 됩니다.

먼저 음식 목록 화면을 관리하기 위한 커스텀 테이블 뷰 컨트롤러(table view controller)의 서브클래스를 만들겠습니다.

To create a subclass of UITableViewController

  1. 메뉴바에서 File > New > File을 클릭하세요(단축키 Commnad-N)

  2. 다이얼로그의 왼쪽에서 iOS를 선택하고 오른쪽에서 Cocoa Touch Class를 선택하세요

  3. Next를 클릭하세요

  4. Class필드에 Meal이라고 입력하세요

  5. Subclass of필드에서 UITableViewController를 선택하세요

    class의 title의 MealTableViewController로 변경될 것입니다. 그대로 두세요

  6. Also Create XIB file이 체크 해제되어있는지 확인하세요

  7. Language 옵션이 Swift로 되어있는지 확인하세요

  8. Next를 클릭하세요

  9. 다른 옵션들은 모두 디폴트 상태 그대로 둔 채, Create를 클릭하세요

    MealTableViewController.swfit파일이 생성될 것입니다. UITableViewController를 상속 받는 커스텀 테이블 뷰 컨트롤러 파일입니다.

이 커스텀 서브클래스에서 Meal 객체들의 리스트를 저장하기 위한 프로퍼티를 정의할 것입니다. swift 스탠다드 라이브러리는 아이템들의 리스트를 관리하기에 유용한 배열(Array)라는 컬레션을 제공합니다.

To load the initial data

  1. standart editor 화면으로 세팅하고, project navigator와 utility area를 열어주세요

    image
  2. MealTableViewController.swift파일을 열어주세요

  3. 클래스 선언 라인 바로 밑에 아래의 주석과 프로퍼티를 추가해주세요

    1. // MARK: Properties
    2. var meals = [Meal]()

    이 코드는 MealTableViewController에 프로퍼티를 선언하고 디폴트(Meal 객체의 비어있는 배열) 값으로 초기화 한 것입니다. 또한 상수가 아닌 변수(var)로 선언하여 변경가능한(mutable) 배열을 만들었기 때문에 추후에 값을 추가하거나 제거하는 등의 변경 작업이 가능합니다.

  4. viewDidLoad() 메서드 밑에 아래 메서드를 선언해주세요

    1. func loadSampleMeals() {
    2. }

    이 함수는 앱에 샘플 데이터를 로드시키기 위한 일종의 헬퍼 메서드(helper method)입니다.

  5. 아래와 같이 loadSampleMeals() 메서드의 구현부를 작성해주세요. 아래의 코드는 Meal클래스의 객체를 생성하고 각 프로퍼티에 적절한 값을 할당하여 초기화 하고 있습니다.

    1. let photo1 = UIImage(named: "meal1.jpg")!
    2. let meal1 = Meal(name: "Caprese Salad", photo: photo1, rating: 4)!
    3. let photo2 = UIImage(named: "meal2.jpg")!
    4. let meal2 = Meal(name: "Chicken and Potatoes", photo: photo2, rating: 5)!
    5. let photo3 = UIImage(named: "meal3.jpg")!
    6. let meal3 = Meal(name: "Pasta with Meatballs", photo: photo3, rating: 3)!

    프로젝트에 추가했던 이미지 파일의 이름과 동일한지 확인 하세요

  6. 위에서 만든 3개의 Meal객체를 meals 배열에 추가하는 코드를 작성하세요(*역자 : "+=" 연산자가 작동하지 않는다면, meals.append(meal1) 처럼 메서드를 사용해서 추가해주세요. meal2랑 meal3 도 마찬가지입니다)

    1. meals += [meal1, meal2, meal3]
  7. viewDidLoad()메서드를 찾아주세요. 템플릿 구현부가 아래와 같이 생성되어 있을 것입니다.

    1. override func viewDidLoad() {
    2. super.viewDidLoad()
    3. // Uncomment the following line to preserve selection between presentations
    4. // self.clearsSelectionOnViewWillAppear = false
    5. // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    6. // self.navigationItem.rightBarButtonItem = self.editButtonItem()
    7. }

    메서드에 생성된 템플릿 구현부는 Xcode가 파일 생성시 자동으로 추가한 것으로 유용한 도움말 역할을 하지만, 이번 레슨에서는 필요 없는 내용입니다.

  8. viewDidLoad()메서드에서 주석들을 지우고, super.viewDidLoad() 아래에 샘플 데이터를 로드하기 위한 코드를 작성하세요

    1. // Load the sample data.
    2. loadSampleMeals()

    view가 로드될 때 샘플 데이터를 배열에 추가하는 헬퍼메서드를 호출하였습니다. viewDidLoad()메서드 내부에 직접 코딩해도 되지만, 이렇게 메서드로 따로 작성하여 모듈화하면, 재활용이 가능하며 코드의 가독성도 좋아집니다.

현재까지 작업한 viewDidLoad()메서드의 모습은 아래와 같습니다.

  1. override func viewDidLoad() {
  2. super.viewDidLoad()
  3. // Load the sample data.
  4. loadSampleMeals()
  5. }

loadSampleMeals()메서드의 모습은 아래와 같습니다.

  1. func loadSampleMeals() {
  2. let photo1 = UIImage(named: "meal1.jpg")!
  3. let meal1 = Meal(name: "Caprese Salad", photo: photo1, rating: 4)!
  4. let photo2 = UIImage(named: "meal2.jpg")!
  5. let meal2 = Meal(name: "Chicken and Potatoes", photo: photo2, rating: 5)!
  6. let photo3 = UIImage(named: "meal3.jpg")!
  7. let meal3 = Meal(name: "Pasta with Meatballs", photo: photo3, rating: 3)!
  8. meals += [meal1, meal2, meal3]
  9. }

Checkpoint: Build your project by choosing Product > Build. It should build without errors. Command-B(메뉴바에서 Product > Build)를 통해 빌드를 수행해보세요. 아무런 에러도 발생하지 않아야 합니다.

Display the Data

UITableViewController를 상속 받아 만든 커스텀 테이블 뷰 컨트롤러 클래스인 MealTableViewController는 샘플 음식 데이터를 저장하고 있는 배열을 갖게 되었습니다. 이제 이 샘플데이터들을 UI상에 노출 시키는 작업을 해보겠습니다.

테이블 뷰에 동적인 데이터를 노출하기 위해서는  데이터소스(data source)와 델리게이트(delegate)가 필요합니다. 테이블 뷰 데이터소스는 이름이 의미하는 바와 같이 노출할 데이터를 제공하는 역할을 합니다. 테이블 뷰 델리게이트는 셀의 선택과 관련된 작업 및 행의 높이와 같은 데이터를 노출하는 것과 관련된 측면을 관리합니다. 

UITableViewController는 디폴트로 데이터소스 프로토콜(UITableViewDataSource)과 델리게이트 프로토콜(UITableViewDelegate)를 따르도록 정의되어 있습니다. 따라서 테이블 뷰 컨트롤러 상에서 데이터소스와 델리게이트를 프로토콜 메서드를 구현하여 테이블 뷰가 작동하도록 작업하면 됩니다.

구현해야할 데이터소스의 프로토콜 메서드는 아래와 같습니다.

  1. func numberOfSectionsInTableView(tableView: UITableView) -> Int
  2. func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
  3. func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

numberOfSectionInTableView(_:)메서드는 테이블뷰에 노출할 섹션(Section)의 수를 설정하는 메서드입니다. 섹션이란 테이블 뷰상에서 특정 의미군으로 묶은 셀의 그룹입니다. 많은 양의 데이터를 구분하여 노출해야할 때 섹션별로 그룹화하여 사용하는 경우가 있으며 ,이 메서드를 통해 사용할 섹션의 수를 설정하면 됩니다. 하지만 FoodTracker 앱에서는 간단하게 하나의 섹션에 모든 데이터를 노출하도록 하겠습니다. 

To display a section in your table view

  1. MealTableViewController.swift 파일에서 데이터 소스 프로토콜 메서드인 numberOfSectionInTableView(_:) 메서드를 찾으세요

    1. override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    2. // #warning Incomplete implementation, return the number of sections
    3. return 0
    4. }
  2. 리턴하는 값을 0에서 1로 변경하고 warning 주석은 제거해주세요

    1. override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    2. return 1
    3. }

    위의 코드는 테이블 뷰에서 사용할 섹션의 수가 한개라고 반환하고 있습니다. #warning 주석은 이 메서드를 구현하라는 의미이므로 이제 삭제해도 됩니다.

다음으로 구현할 데이터소스 프로토콜 메서드는 tableView(_: numberOfRowsInSection:)메서드 입니다. 이 메서드는 주어진 섹션에서 노출할 행(Row)의 수를 설정하는 메서드입니다. 한 행당 하나의 음식 정보를 노출하는 테이블 뷰이므로, 섹션에서 사용할 행의 수는 음식(Meal) 객체의 수와 동일합니다. 즉, meals 배열의 항목 수(Meal 객체 수)와 동일합니다.

To return the number of rows in your table view

  1. MealTableViewController.swift파일에서 tableView(_:numberOfRowsInSection:)메서드를 찾아주세요

    1. override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    2. // #warning Incomplete implementation, return the number of rows
    3. return 0
    4. }

    이 메서드에서 해야할 일은 주어진 섹션에서 사용할 행의 수를 반환하는 작업입니다. 사용할 행의 수는 meals 배열에 저장되어 있는 Meal객체의 수입니다. 배열은 자신의 항목 수를 count라는 프로퍼티에 저장하고 있습니다. 즉, meals.count 프로퍼티 값을 사용할 행의 수로 반환하면 됩니다.

  2. 아래와 같이 리턴하는 행의 수를 meals.count로 변경하고, 주석은 지워주세요

    1. override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    2. return meals.count
    3. }

마지막으로 구현할 메서드는 tableView(_:cellForRowAtIndexPath) 입니다. 이 메서드는 주어진 행에 노출할 셀을 설정 및 노출하는 작업을 수행합니다. 테이블 뷰에서 각 행은 하나의 셀을 갖고 있으며, 이 셀에 표시되는 내용이 행에 노출되게 됩니다. (IndexPath에는 해당 행의 Section 및 Row에 대한 정보가 저장되어 있습니다.)

몇 개의 행만 노출하는 테이블 뷰의 경우에는 한 화면에 모든 행이 노출 될 것입니다. 따라서 이 경우에는 모든 행에 대하여 이 메서드가 각각 호출될 것입니다. 하지만 수많은 행으로 구성된 테이블 뷰의 경우에는 모든 행에 대해 이 메서드를 호출하여 사용하는 것은 메모리를 비롯한 각종 자원이 낭비되며 매우 비효율적인 방식입니다. 따라서 이런 경우에는 현재 화면에 표시되는 행에 대해서만 이 메서드를 호출하여 셀을 생성하는 것이 효율적입니다.

테이블 뷰의 각 행에 해당하는 Meal객체를 meals 배열로 부터 받아와 cell에 설정하고, cell의 프로퍼티(name, photo, rating)에는 Meal객체의 프로퍼티 값을 설정해야 합니다.

To configure and display cells in your table view

  1. MealTableViewController.swift 파일에서 tableView(_:cellForRowAtIndexPath:)메서드에 적용된 주석 처리를 제거해주세요(/* 와 */ 를 지우면 됩니다)

    아래와 같이 템플릿 구현부가 작성된 메서드가 보이게 됩니다.

    1. override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    2. let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as! UITableViewCell
    3. // Configure the cell...
    4. return cell
    5. }

    각 행이 화면에 나타날 때마다 이 메서드가 호출되어 노출해야할 cell을 해당 섹션의 해당 행에 전달합니다. 메서드 구현부를 보면 tableview객체의 dequeueReusableCellWithIdentifier 메서드를 호출하여 identifier에 해당하는 셀에 노출될 indexPath를 설정하여 UITableViewCell 객체 형태로 생성합니다. 그리고 해당 indexPath에 노출할  cell을 반환하면서 전체 메서드 구현부를 종료하고 있습니다. 즉, 이 메서드는 identifier에 해당하는 커스텀 셀을 IndexPath에 맞는 행에게 반환하는 메서드입니다. (IndexPath는 섹션과 행 정보를 담고있습니다)

    이 코드를 FoodTracker앱에 적용하기 위해서는 "reuseIdentifier" 부분을 이전에 스토리보드에서 프로토타입 셀에 설정하였던 identifier(MealTableViewCell)로 변경해야합니다.

  2. 메서드 구현부의 첫 부분에 아래의 코드를 작성해주세요

    1. // Table view cells are reused and should be dequeued using a cell identifier.
    2. let cellIdentifier = "MealTableViewCell"

    위의 코드는 스토리보드에서 프로토타입 셀에 설정했던 identifier를 상수로 선언하고 있습니다.

  3. tableView.dequeueReusableCellWithIdentifier메서드의 "reuseIdentifier" 파라미터를 아래와 같이 스토리보드에서 프로토타입 셀에 설정했던 identifier로 변경해주세요

    1. let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! UITableViewCell
  4. 커스텀 셀로 사용하기 위해 만든 MealTabeViewCell클래스가 있기 때문에, dequeueReusableCellWithIdentifer 메서드의 반환 타입을 UITableViewCell이 아닌 MealTableViewCell로 변경해주세요.

    1. let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! MealTableViewCell
  5. 다음 라인에 아래의 코드를 작성해주세요

    1. // Fetches the appropriate meal for the data source layout.
    2. let meal = meals[indexPath.row]

    이 코드는 현재 행에서 노출할 Meal객체를 meals배열에서 가져옵니다. (indexPath에는 section 및 row 값이 저장되어 있습니다)

  6. "//Configure the cell" 주석을 삭제하고 아래의 코드를 작성하세요

    1. cell.nameLabel.text = meal.name
    2. cell.photoImageView.image = meal.photo
    3. cell.ratingControl.rating = meal.rating

    이 코드는 커스텀 테이블 뷰 셀(MealTableViewCell)에 포함되어 있는 각 뷰 객체에 Meal객체의 프로퍼티 값을 할당하여 노출하는 작업을 하고 있습니다. 

완성된 tableView(_:cellForRowAtIndexPath:)메서드의 모습은 아래와 같습니다.

  1. override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  2. // Table view cells are reused and should be dequeued using a cell identifier.
  3. let cellIdentifier = "MealTableViewCell"
  4. let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! MealTableViewCell
  5. // Fetches the appropriate meal for the data source layout.
  6. let meal = meals[indexPath.row]
  7. cell.nameLabel.text = meal.name
  8. cell.photoImageView.image = meal.photo
  9. cell.ratingControl.rating = meal.rating
  10. return cell
  11. }

우리가 작업한 내용을 실제 앱에 노출하기 위해 필요한 마지막 작업은 MealTableViewController.swift의 소스코드를 스토리보드 상의 scene으로 연결하는 것입니다. 스토리보드에 생성한 tableViewController 화면이 MealTableViewController에 의해 관리되도록 하는 작업입니다.

To point the table view controller scene to MealTableViewController.swift

  1. 스토리보드를 열어주세요

  2. 아래 화면과 같이 scene dock 에서 table view controller를 선택해주세요. 전체 화면에 파란색 윤곽선이 생깁니다.

    image
  3. Identity inspector를 열어주세요

  4. Identity Inspector에서 Class필드의 값을 아래 화면과 같이 MealTableViewController로 선택해주세요

    image

Checkpoint: 앱을 실행시켜주세요. viewDidLoad()메서드에서 준비해둔 샘플데이터들이 테이블 뷰의 각 셀에 표시됩니다. 현재 테이블뷰셀이 상단바(status bar)영역을 덮고 있는 상태입니다. 다음 레슨에서 이 부분을 수정하는 작업을 진행해 보겠습니다.

image

Prepare the Meal Scene for Navigation

FoodTracker앱에서 네비게이션(다른 scene으로 이동) 기능을 구현하기 위한 준비작업으로 필요없는 코드 및 UI는 제거하도록 하겠습니다.

To clean up unused pieces of the project

  1. Open your storyboard and look at the meal scene. 스토리 보드를 열고 상세화면(meal scene)이 보이게 화면을 조정하세요

    현재 음식 상세화면의 모습은 아래와 같습니다.

    image
  2. "Meal Name" 라벨을 선택하고 Deleter키를 눌러 삭제해주세요

    스택뷰(stackView)에 남은 다른 뷰 객체들의 위치는 자동으로 조정됩니다.

    image
  3. ViewController.swift 파일을 열어주세요

  4. textFieldDidEndEditing(_:)메서드를 찾아주세요

    1. func textFieldDidEndEditing(textField: UITextField) {
    2. mealNameLabel.text = textField.text
    3. }
  5. 라벨의 text 프로퍼티 값을 설정하는 아래의 코드를 삭제하세요

    1. mealNameLabel.text = textField.text

    이 부분은 나중에 다른 내용을 추가할 예정입니다.

  6. "mealNameLabel" outlet을 찾아서 삭제해주세요

    1. @IBOutlet weak var mealNameLabel: UILabel!

Because you now have two view controllers in your project, it makes sense to give ViewController.swift a more meaningful name. 프로젝트에 두개의 뷰 컨트롤러가 있는 상태이므로, ViewController.swift 에도 좀더 의미있는 이름을 부여하도록 하겠습니다.(음식 상세화면을 의미하는 이름으로 바꾸겠습니다)

To rename the ViewController.swift file

  1. project navigator에서 ViewController.swift 파일을 선택하고 리턴키를 눌러주세요

    파일 이름을 변경할 수 있는 모드가 됩니다.

  2. "MealViewcontroller.swift" 로 이름을 변경하고, 리턴키를 누르세요

  3. 소스코드 파일 내용에서 클래스 선언부를 찾아주세요

    1. class ViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
  4. 클래스 이름을 "MealViewController"로 변경해주세요

    1. class MealViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
  5. 소스코드 파일의 맨 위에 있는 주석 부분에서도 ViewController.swift를 MealViewController.swift로 변경해주세요

  6. 스토리보드를 열어주세요

  7. Select the meal scene by clicking on its scene dock. - scene dock에서 음식 상세화면(meal scene)을 클릭하세요

    image
  8. 상세화면이 선택된 상태에서 Identity Inspector를 열어주세요

  9. Identity Inspector에서 Class 필드의 값을 ViewController에서 MealViewController로 변경해주세요

    image

Checkpoint: 앱을 실행시보세요. 이전과 동일하게 잘 작동해야합니다.

현재 Xcode에서 음식 상세화면으로 이동할 방법이 없다는 경고를 노출할 것입니다. 다음 레슨에서 네비게이션(scene간 이동) 기능을 구현해볼 예정입니다.


댓글