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

[한글 번역_10] Start Developing iOS Apps (Swift) - Working with Table Views > Implement Edit and Delete Behavior

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

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

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

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

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

감사합니다.



Implement Edit and Delete Behavior

 이번 레슨에서는 기존에 있던 meal을 편집하거나 삭제하는 기능을 구현해보겠습니다.

Learning Objectives

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

  • push/modal navigation 구분하기

  • 프리젠테이션 스타일에 따라 view controller 사라지게 하기

  • 다운 캐스팅을 위한 다양한 cast operator 사용하기

  • 복잡한 조건을 체크하기 위해 optional binding 이용하기

  • segue identifier를 이용하여 어떤 segue가 발생했는지 확인하기

Allow Editing of Existing Meals

현재 FoodTracker앱은 meal list에 새로운 meal을 추가하는 기능을 제공하고 있습니다. 이제 기존의 meal을 편집하고 삭제하는 기능을 구현해보겠습니다.

meal list에서 meal cell을 탭하면 해당 meal에 대한 정보를 보여주는 meal scene을 노출하고, 내용을 변경한 후 Save버튼을 눌르면 meal list에서도 업데이트가 되도록 구현하겠습니다.

To configure the table view cell

  1. assistant editor가 열려있다면 툴바를 통해 standard editor로 돌아오세요

    image
  2. Main.storyboard 를 열어주세요

  3. 캔버스에서 table view cell을 선택하세요

  4. control을 누른채 드래그하여 meal scene으로 연결하세요

    image

    Selection Segue 메뉴가 나타납니다.

    image
  5. Selection Segue 메뉴에서 "show"를 선택하세요

  6. meal list와 meal scene 사이의 navigation controller를 아래로 드래그하여 아래와 같이 새로운 segue가 나타나게 하세요

    image

    잘 안 보이면 Command-Minus(-)를 눌러 zoom out 할 수 있습니다.

  7. 캔버스에서 새로 추가된 segue를 선택하세요

    image
  8. Attributes inspector로 가서 Identifier 필드의 값을 "ShowDetail"로 입력하고 리턴키를 누르세요

    image

이 segue가 동작하면, meal scene의 view controller를 meal list가 삽입되어있는  navigation stack의 위에 쌓습니다. 그 결과 meal scene이 push스타일(오른쪽으로 화면이 밀림)로 노출됩니다.

Checkpoint: 앱을 실행해보세요. meal list scene에서 table view cell을 탭하면 meal scene으로 넘어가게 됩니다. 하지만 새로운 meal을 만들기 위한 화면으로 컨텐츠가 비어있습니다. 우리가 원하는 것은 우리가 탭한 cell에 해당하는 meal 의 화면입니다.

현재 meal scene으로 가기 위한 segue가 두개가 존재하는 상황입니다. 따라서 사용자가 새로운 meal을 만드려는 것인지, 아니면 기존의 meal을 편집하려는 것인지를 확인할 수 있어야 합니다.

segue가 수행되기 전에 호출되는 prepareForSegue(_:sender:)메서드를 통해 어떤 segue가 발생하려는지 파악할 수 있으며, 각 segue에 해당하는 meal scene을 보여줄 수 있습니다. 이전에 segue에 각각 할당했던 identifier을 통해 segue를 구별할 수 있습니다.(이전에 추가했던 modal segue에는 "AddItem", 방금 추가한 show segue에는 "ShowDetail"이 각각 설정되어 있습니다.)

To identify which segue is occurring

  1. MealTableViewController.swift 파일을 열어주세요

  2. MealTableViewController.swift파일에서 prepareForSegue(_:sender:) 메서드를 찾아서 주석을 풀어주세요( /* 와 */를 지우면 됩니다) 

    템플릿 구현부는 아래와 같을 것입니다. 테이블 뷰에서 셀을 탭하거나, 네비게이션 바에서 add(+)버튼을 탭하면 segue가 실행되기 직전 아래 메서드가 실행됩니다. segue 파라미터에는 발생하는 segue에 대한 각종 정보가 들어가며, sender파라미터에는 탭이 발생한 객체가 UIViewController타입으로 들어가게 됩니다

    1. // MARK: - Navigation
    2. // In a storyboard-based application, you will often want to do a little preparation before navigation
    3. override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    4. // Get the new view controller using segue.destinationViewController.
    5. // Pass the selected object to the new view controller.
    6. }

    MealTableViewController는 UITableViewController의 서브클래스이기 때문에, prepareForSegue(_:sender:)가 기본적으로 선언되어 있습니다.

  3. 구현부에 있는 주석을 지우고 아래의 if-else 구문을 작성해주세요

    1. if segue.identifier == "ShowDetail" {
    2. }
    3. else if segue.identifier == "AddItem" {
    4. }

    이 코드는 각각의 segue에 할당해 두었던 identifier를 통해 어떤 segue가 수행될지 파악할 수 있습니다. identifier가 "ShowDetail"이면 테이블 뷰의 셀을 눌러 상세화면으로 이동해 편집하려는 것입니다. identifier가 "AddItem"이면 Add버튼(+)을 눌러 새로운 meal을 생성하기 위한 화면으로 이동하려는 것입니다.

  4. 첫 번째 if문(meal을 편집하려는 경우)의 구현부에 아래의 코드를 추가하세요

    1. let mealDetailViewController = segue.destinationViewController as! MealViewController

    이 코드는 화면전환을 통해 이동하려는 목적지 뷰컨트롤러인 segue.destinationViewController를 강제 형변환 연산자(forced type cats operator : as!)를 이용하여 MealViewController로 다운캐스팅 하고 있습니다. 지금까지는 as( ? ) 형태로 물음표를 사용하였으나 이번에는 느낌표( ! )를 사용하였습니다. 강제 형변환 연산자는 무조건 강제로 형변환을 수행하겠다는 의미입니다. 형변환(cast)이 성공하면 segue.destinationViewController 를 MealViewController 타입으로 형변환하여 local 상수 mealDetailViewController에 할당합니다. 하지만 형변환이 실패한다면, 앱은 실행(runtime) 중에 충돌을 일으키게 됩니다.

    따라서 형 변환이 반드시 성공한다고 확신하는 경우에만 강제 형변환(forced cast)를 사용해야합니다. 만약 형 변환에 실패할 가능성이 있는 경우에는 앱 작동 중에 충돌이 발생하여 종료될 수 있으므로 as? (optional type cast operator)을 사용해야 합니다.

  5. 다음 라인에 아래와 같이 if 문을 추가해주세요(중첩된 형태의 if 문입니다)

    1. // Get the cell that generated this segue.
    2. if let selectedMealCell = sender as? MealTableViewCell {
    3. }

    테이블 뷰의 셀을 탭하면, segue가 발생하기 전에 이 메서드가 실행되며 sender 파라미터에 탭이 발생한 셀 객체가 UIViewController 타입으로 전달됩니다. 따라서 as?(optional type cast operator)를 통해 MealTableViewCell 타입으로 다운캐스팅하고 지역 상수로 선언한 selectedMealCell에 할당하여 사용해야합니다. 형 변환에 성공하면 지역변수에 값이 할당 되고 if 문이 수행되지만, 형변환이 실패한다면 nil값이 반환되고 if문은 수행되지 않습니다.

  6. if 문 안에 아래의 코드를 추가하세요

    1. let indexPath = tableView.indexPathForCell(selectedMealCell)!
    2. let selectedMeal = meals[indexPath.row]
    3. mealDetailViewController.meal = selectedMeal

    This code fetches the Meal object corresponding to the selected cell in the table view. It then assigns that Meal object to the meal property of the destination view controller, an instance of MealViewController. (You’ll configure MealViewController to display the information from its mealproperty when it loads.) - 이 코드는 테이블 뷰에서 선택된 cell에 해당하는 Meal객체를 불러와서 destination view controller(MealViewController)의 meal 프로퍼티에 할당합니다. 화면전환이 발생하고 나면 MealViewController에서 이 meal프로퍼티의 내용을 노출하는 작업을 해야합니다.

  7. 기존에 만든 else 구문 안에는 아래의 print 구문을 추가하세요

    1. print("Adding new meal.")

    Add(+)버튼을 눌러 새로운 음식을 추가하는 화면으로 넘어가기 전에 필요한 작업은 전혀 없습니다. 따라서 아무런 구현도 하지 않아도 되지만, 로그를 남기는 것은 어디에서 무슨 일이 발생하는지 파악하는데 유용합니다.

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

  1. override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  2. if segue.identifier == "ShowDetail" {
  3. let mealDetailViewController = segue.destinationViewController as! MealViewController
  4. // Get the cell that generated this segue.
  5. if let selectedMealCell = sender as? MealTableViewCell {
  6. let indexPath = tableView.indexPathForCell(selectedMealCell)!
  7. let selectedMeal = meals[indexPath.row]
  8. mealDetailViewController.meal = selectedMeal
  9. }
  10. }
  11. else if segue.identifier == "AddItem" {
  12. print("Adding new meal.")
  13. }
  14. }

Now that you have the logic implemented, you need to do a small amount of work in MealViewController.swift to make sure the UI updates correctly. Specifically, when an instance of MealViewController (the meal scene) gets created, its views should be populated with data from its mealproperty, if that data exists. Recall that the appropriate place to do this type of setup work is in the viewDidLoad() method. - 테이블 뷰에서 필요한 로직의 구현은 모두 완료되었으며, MealViewController가 전달받은 meal프로퍼티의 내용을 잘 표시하도록 하는 작업만 하면 됩니다. segue가 발생하여 MealViewController 객체 생성되어 화면에 노출될 때 viewDidLoad()메서드가 호출됩니다. 따라서 이 메서드 안에서 전달 받은 meal프로퍼티의 내용을 UI에 표시하는 내용을 구현하면 됩니다. 하지만 Add(+)버튼 등을 눌러 전달 받은 데이터가 없는 경우엔 아무 것도 표시해서는 안됩니다.

To update the implementation of viewDidLoad

  1. MealViewController.swift 파일을 열어주세요

  2. MealViewController.swift 파일에서 viewDidLoad() 메서드를 찾아주세요

    1. override func viewDidLoad() {
    2. super.viewDidLoad()
    3. // Handle the text field’s user input via delegate callbacks.
    4. nameTextField.delegate = self
    5. // Enable the Save button only if the text field has a valid Meal name.
    6. checkValidMealName()
    7. }
  3. nameTextField.delegate = self 라인 밑에 아래 코드를 추가해주세요

    1. // Set up views if editing an existing Meal.
    2. if let meal = meal {
    3. navigationItem.title = meal.name
    4. nameTextField.text = meal.name
    5. photoImageView.image = meal.photo
    6. ratingControl.rating = meal.rating
    7. }

    This code sets each of the views in MealViewController to display data from the meal property if the meal property is non-nil, which happens only when an existing meal is being edited. - 이 코드는 MealViewController에 있는 각각의 view들에 meal 프로퍼티의 내용을 노출하도록 구현하고 있습니다. 전달 받은 meal이 있는 경우(meal프로퍼티가 nil이 아닌 경우)에만 지역 상수에 값이 할당 되어 if 문이 수행 되며, 이는 테이블 뷰의 셀을 눌러 진입한 것으로 음식 정보를 편집 하는 경우입니다. (Add버튼을 눌러 진입한 경우에는 meal프로퍼티가 nil이 므로 아래의 if문은 수행되지 않습니다) 

완성된 viewDidLoad()메서드의 모습은 아래와 같습니다.

  1. override func viewDidLoad() {
  2. super.viewDidLoad()
  3. // Handle the text field’s user input via delegate callbacks.
  4. nameTextField.delegate = self
  5. // Set up views if editing an existing Meal.
  6. if let meal = meal {
  7. navigationItem.title = meal.name
  8. nameTextField.text = meal.name
  9. photoImageView.image = meal.photo
  10. ratingControl.rating = meal.rating
  11. }
  12. // Enable the Save button only if the text field has a valid Meal name.
  13. checkValidMealName()
  14. }

Checkpoint: 앱을 실행시켜보세요. 테이블 뷰의 cell을 클릭하면 해당 음식에 대한 정보가 노출 되는 meal scene으로 이동하게 됩니다. 하지만 Save버튼을 누르면 기존 음식 정보를 업데이트 하는 것이 아니라, 새로운 meal을 추가해버립니다. 이 부분을 제대로 작동하도록 작업 해보겠습니다.

image

unwindToMealList(_:) 액션메서드를 수정해서 새로운 meal을 추가하는 것과 기존 meal을 편집하는 두 케이스를 관리할 수 있도록 구현하겠습니다. 참고로 이 메서드는 Save버튼을 Exit로 연결할 때 선택한 메서드로, Save버튼을 눌러 MealTableViewController로 복귀하면서 호출되는 IBActon 메서드입니다. 따라서  오직 Save버튼을 누를 때에만 호출되며, Cancel버튼과는 무관한 메서드입니다.

To update the implementation of unwindToMealList(_:) to add or replace meals

  1. MealTableViewController.swift 파일을 여세요

  2. unwindToMealList(_:) 메서드를 찾아주세요

    1. @IBAction func unwindToMealList(sender: UIStoryboardSegue) {
    2. if let sourceViewController = sender.sourceViewController as? MealViewController, meal = sourceViewController.meal {
    3. // Add a new meal.
    4. let newIndexPath = NSIndexPath(forRow: meals.count, inSection: 0)
    5. meals.append(meal)
    6. tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Bottom)
    7. }
    8. }
  3. 처음에 나오는 if문에 아래의 if문을 추가해주세요

    1. if let selectedIndexPath = tableView.indexPathForSelectedRow {
    2. }

    이 if문의 조건은 테이블 뷰의 행이 선택되었는지 여부를 체크합니다. 즉, 사용자가 table view cell 중 하나를 탭하여 편집하기 위해 들어 왔는지를 확인하는 것입니다. 이 경우, 지역 상수 selectedIndexPath에 선택된 행의 indexPath값을 할당하고 if 문을 실행 합니다. 그렇지 않은 경우라면 Add(+)버튼을 눌러서 들어온 경우입니다.

  4. if문의 구현부에 아래의 코드를 작성해주세요

    1. // Update an existing meal.
    2. meals[selectedIndexPath.row] = meal
    3. tableView.reloadRowsAtIndexPaths([selectedIndexPath], withRowAnimation: .None)

    첫 번째 코드는 선택된 행에 해당하는 meals 배열의 값을 수정된 meal객체로 교체합니다. 두 번째 코드는 변경된 데이터를 노출하기 위해 지정된 행(들)을 다시 로드(reload)하여 UI를 업데이트합니다.

  5. if문 다음에 아래와 같이 else절을 추가하여 남아 있는 기존의 코드들을 삽입해주세요

    1. else {
    2. // Add a new meal.
    3. let newIndexPath = NSIndexPath(forRow: meals.count, inSection: 0)
    4. meals.append(meal)
    5. tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Bottom)
    6. }

    else 절의 구현부 내용을 들여쓰기 해주셔야합니다. 전체 코드를 선택한 다음 Control-I를 누르면 자동으로 들여쓰기가 조정됩니다.

    이 else 절은 사용자가 테이블 뷰에서 어떠한 행도 선택 되지 않은 상태에서 meal scene으로 진입한 경우에 수행됩니다. 즉, Add버튼을 눌러 meal scene이 노출된 상황으로 새로운 음식을 추가하는 작업을 해야합니다 (*역자 : 현재 meals배열의 항목 수를 체크하고, 그 뒤에다가 새롭게 추가된 meal을 추가하는 작업으로 변경된 사항은 없습니다.)

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

  1. @IBAction func unwindToMealList(sender: UIStoryboardSegue) {
  2. if let sourceViewController = sender.sourceViewController as? MealViewController, meal = sourceViewController.meal {
  3. if let selectedIndexPath = tableView.indexPathForSelectedRow {
  4. // Update an existing meal.
  5. meals[selectedIndexPath.row] = meal
  6. tableView.reloadRowsAtIndexPaths([selectedIndexPath], withRowAnimation: .None)
  7. }
  8. else {
  9. // Add a new meal.
  10. let newIndexPath = NSIndexPath(forRow: meals.count, inSection: 0)
  11. meals.append(meal)
  12. tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Bottom)
  13. }
  14. }
  15. }

Checkpoint: 앱을 실행해보세요. 이제 테이블 뷰의 셀을 누르면 해당 음식에 대한 정보를 보여주는 meal scene화면으로 이동합니다. 또한 Save버튼을 누르면 기존 음식 정보를 업데이트 합니다(더이상 새로운 음식을 추가하지 않습니다.)

image

Cancel an Edit to an Existing Meal

음식을 추가하거나 편집하기 위해 들어왔다가, 그냥 취소하고 이전화면으로 돌아가는 경우도 있습니다. 이를 위해 Cancel버튼을 누르면 어떠한 작업 내용도 반영하지 않고 음식 목록 화면으로 돌아가는 작업을 진행하겠습니다.

Add(+)버튼을 눌러 Modal present 방식으로 진입 했다면 dismissViewControllerAnimated(_:completion)메서드를 통해 현재 화면을 날려버리면 됩니다. 테이블 뷰의 셀을 눌러 push navigation 방식으로 진입한 경우에는 meal scene을 보여주고 있는 네비게이션 컨트롤러를 통해 이전 화면으로 돌아가면 됩니다. 따라서 사용자가 Cancel 버튼을 눌렀을 때 어떤 타입으로 현재 화면에 진입했는지 확인하고, 위의 케이스에 따라 구현하면 됩니다.

To change the implementation of the cancel action

  1. MealViewController.swift 파일을 열어주세요

  2. cancel(_:) 액션 메서드를 찾아주세요

    1. @IBAction func cancel(sender: UIBarButtonItem) {
    2. dismissViewControllerAnimated(true, completion: nil)
    3. }

    현재는 Add(+)버튼을 눌러 진입한 경우만을 한정하여 dismissViewControllerAnimated메서드를 이용해 meal scene을 날려버리는 기능만 구현되어 있습니다. 하지만 이제는 음식 정보를 편집하기 위해 테이블 뷰의 셀을 눌러 접근한 경우에 대한 케이스도 구현해야합니다.

  3. Cancel(_:) 액션 메서드의 구현부 맨 첫부분에 아래의 코드를 추가하세요

    1. // Depending on style of presentation (modal or push presentation), this view controller needs to be dismissed in two different ways.
    2. let isPresentingInAddMealMode = presentingViewController is UINavigationController

    이 코드는 현재의 scene을 표시하고 있는 viewController 가 UINavigationController타입인지 여부를 체크하여 지역상수인 isPresentingInAddMealMode에 Boolean 값을 할당합니다. 이 상수의 값이 true이면 Add버튼을 통해 노출된 화면임을 의미하고, false이면 테이블 뷰의 셀을 탭하여 진입한 화면임을 의미합니다. Add버튼을 통해 진입한 경우, Meal scene은 자기 자신의 네비게이션 컨트롤러에 삽입된 형태이기 때문에, Meal scene을 보여주고 있는 뷰 컨트롤러는 네비게이션 컨트롤러가 됩니다.

  4. 다음 라인에 아래의 if 절을 추가하세요. 그리고 dismissViewControllerAnimated 메서드를 호출하는 코드를 이 if 절 안으로 옮겨주세요

    1. if isPresentingInAddMealMode {
    2. dismissViewControllerAnimated(true, completion: nil)
    3. }

    dismissViewControllerAnimated 메서드는 Cancel 버튼을 누를 때마다 호출 되었던 이전과는 다르게, 이제는 isPresentingInAddMode 가 true인 경우에만 호출됩니다.

  5. if 절 바로 밑에 아래의 else절을 추가해주세요

    1. else {
    2. navigationController!.popViewControllerAnimated(true)
    3. }

    이 코드를 통해 if 절의 내용은 isPresentingInAddMode가 true일 때만 실행되며, else 절의 내용은 isPresentingInAddMode 가 false일 때만 실행됩니다.

    즉, else 절은 meal scene이 meal list scene의 navigation stack의 맨위에 쌓여(push) 노출된 경우에만 수행됩니다. else 절에 구현부에서 호출하는 popViewControllerAnimated 메서드는 네비게이션 컨트롤러의 네비게이션 스택에서 meal scene 의 view controller를 꺼내서(pop) 이전 화면으로 돌아가게 하는 역할을 합니다. 파라미터로 true를 넣어주었기 때문에 애니메이션과 함께 수행됩니다.

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

  1. @IBAction func cancel(sender: UIBarButtonItem) {
  2. // Depending on style of presentation (modal or push presentation), this view controller needs to be dismissed in two different ways.
  3. let isPresentingInAddMealMode = presentingViewController is UINavigationController
  4. if isPresentingInAddMealMode {
  5. dismissViewControllerAnimated(true, completion: nil)
  6. }
  7. else {
  8. navigationController!.popViewControllerAnimated(true)
  9. }
  10. }

Checkpoint: 앱을 실행해보세요. 테이블 뷰의 셀을 누르고 나오는 앱의 편집화면에서 Cancel버튼을 눌러보세요. 음식정보를 수정하지 않고, 이전 화면인 meal list로 돌아오게 될 것입니다.

Support Deleting Meals

테이블뷰에서 셀을 삭제하는 기능도 필요합니다. Edit버튼을 네이게이션 바에 추가하여 편집모드로 전환하여 각 셀을 삭제할 수 있는 기능을 구현해보겠습니다.

To add an Edit button to the table view

  1. MealTableViewController.swift 파일을 열어주세요

  2. viewDidLoad()메서드를 찾으세요

    1. override func viewDidLoad() {
    2. super.viewDidLoad()
    3. // Load the sample data.
    4. loadSampleMeals()
    5. }
  3. super.viewDidLoad()호출하는 코드 아래에 다음의 코드를 작성해주세요.

    1. // Use the edit button item provided by the table view controller.
    2. navigationItem.leftBarButtonItem = editButtonItem()

    이 코드는 아주 특별한 타입의 bar button item객체를 생성하여 테이블 뷰 네비게이션 바의 왼쪽에 추가합니다. 이 버튼은 편집기능을 내장하고 있습니다.

완성된 viewDidLoad()메서드의 모습은 아래와 같습니다.

  1. override func viewDidLoad() {
  2. super.viewDidLoad()
  3. // Use the edit button item provided by the table view controller.
  4. navigationItem.leftBarButtonItem = editButtonItem()
  5. // Load the sample data.
  6. loadSampleMeals()
  7. }

Checkpoint: 앱을 실행시켜보세요. table view의 navigation bar 왼쪽에 Edit 버튼이 보일 것입니다. 이 Edit버튼을 누르면 table view 가 편집모드로 들어가게 됩니다. 하지만 아직 실제로 cell을 지울 수 있는 기능을 구현하지는 않았습니다.

image

테이블 뷰에서 편집 기능을 수행하기 위해서는 테이블뷰의 delegate method인 tableView(_:commitEditingStyle:forRowAtIndexPath:)를 구현해야합니다. 이 delegate method를 이용하면 편집모드에서 테이블 뷰의 각 행(row)들을 관리할 수 있습니다.

You also need to uncomment the implementation of tableView(_:canEditRowAtIndexPath:) to support editing. - 또한 편집 기능을 지원하는 tableView(_:canEditRowAtIndexPath:)메서드도 필요합니다.

즉, Edit 버튼을 통해 편집 모드에 진입할 수 있으며, 각 행을 편집할 수 있기 위해서는 tableView(_:canEditRowAtIndexPath:) 델리게이트 메서드가 구현되어야 있어야 합니다. 이 상태에서 tableView({:commtiEditingStyle:forRowAtIndexPath:)메서드를 통해 실제 행을 삭제하는 작업을 하면 됩니다.

To delete a meal

  1. MealTableViewController.swift 파일에서 tableView(_:commitEditingStyle:forRowAtIndexPath:)메서드에 묶인 주석을 제거해주세요.(/* */를 지우면 됩니다)

    아래와 같이 템플릿 구현부가 작성되어 있습니다. 이 메서드는 실제로 행을 삭제/추가하는 작업을 구현하는 메서드입니다.

    1. // Override to support editing the table view.
    2. override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    3. if editingStyle == .Delete {
    4. // Delete the row from the data source
    5. tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
    6. } else if editingStyle == .Insert {
    7. // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    8. }
    9. }
  2. "// Delete the row from the data source"주석 밑에 아래의 코드를 작성하세요

    1. meals.removeAtIndex(indexPath.row)

    이 코드는 meals 배열에서 Meal객체를 삭제합니다. 바로 아래에 작성되어 있는 템플렛 구현부는 삭제된 Meal에 해당하는 행(row)을 table view에서 삭제해줍니다.

  3. MealTableViewController.swift 파일에서 tableView(_:canEditRowAtIndexPath:) 메서드를 찾아서 주석을 풀어주세요

    이 메서드의 템플릿 구현부는 아래와 같을 것입니다.

    1. // Override to support conditional editing of the table view.
    2. override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    3. // Return false if you do not want the specified item to be editable.
    4. return true
    5. }

지금까지 완성된 tableView(_:commitEditingStyle: forRowAtIndexPath: ) 메서드의 모습은 아래와 같습니다.

  1. // Override to support editing the table view.
  2. override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
  3. if editingStyle == .Delete {
  4. // Delete the row from the data source
  5. meals.removeAtIndex(indexPath.row)
  6. tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
  7. } else if editingStyle == .Insert {
  8. // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
  9. }
  10. }

Checkpoint: 앱을 실행시켜보세요. Edit버튼을 누르면 테이블 뷰가 편집 모드로 진입합니다. 각 cell의 왼쪽에 표시된 인디케이터를 클릭하면 오른쪽에 나타나는 Delete 버튼이 타나납니다. Delete버튼을 누르면 해당 cell이 삭제됩니다. cell을 왼쪽으로 스와이프(swipe)하도 오른쪽에 나타나는 Delete버튼이 나타납니다. 이런 기능들이 모두 테이블 뷰에 내장되어 있으며, 인디케이터/스와이프를 통해 나타난 Delete 버튼을 누르면 테이블 뷰에서 해당 cell이 삭제됩니다.

image


댓글