UITableView 的編輯模式

在稍前表格 UITableView 章節已經介紹過基本的使用方式,其實 UITableView 提供的功能非常的多,這小節會再介紹另一個也是十分常使用到的編輯模式。

以下是本小節目標: todo17

首先在 Xcode 裡,新建一個 Single View Application 類型的專案,取名為 ExEditUITableView 。

並為ViewController建立兩個屬性以供後續使用:

class ViewController: UIViewController {
    var myTableView :UITableView!
    var info = 
      ["林書豪","陳信安","陳偉殷","王建民","陳金鋒","林智勝"]

    // 省略
}

為了方便設置切換 UITableView 編輯模式的按鈕,這邊先在 AppDelegate.swift 設置 導覽控制器 UINavigationController,後續便可在導覽列左右設置按鈕。

首先在 viewDidLoad() 中設置基本設定、 UITableView 及導覽列按鈕:

// 基本設定
let fullsize = UIScreen.mainScreen().bounds.size
self.view.backgroundColor = UIColor.whiteColor()
self.title = "編輯模式"
self.navigationController?.navigationBar.translucent =
  false


// 建立 UITableView
myTableView = UITableView(frame: CGRect(
  x: 0, y: 0, 
  width: fullsize.width, 
  height: fullsize.height - 64), 
  style: .Plain)
myTableView.registerClass(
  UITableViewCell.self, forCellReuseIdentifier: "Cell")
myTableView.delegate = self
myTableView.dataSource = self
myTableView.allowsSelection = true
self.view.addSubview(myTableView)


// 導覽列左邊及右邊按鈕 編輯 & 新增
myTableView.setEditing(true, animated: false)
self.editBtnAction()

上述將導覽列按鈕另外設置在一個方法editBtnAction()中,以供切換編輯模式時可以一併變動。

切換編輯模式

按下編輯按鈕來切換編輯模式,如下:

// 按下編輯按鈕時執行動作的方法
func editBtnAction() {
    myTableView.setEditing(
      !myTableView.editing, animated: true)
    if (!myTableView.editing) {
        // 顯示編輯按鈕
        self.navigationItem.leftBarButtonItem =
          UIBarButtonItem(barButtonSystemItem: .Edit,
          target: self, 
          action:
            #selector(ViewController.editBtnAction))

        // 顯示新增按鈕
        self.navigationItem.rightBarButtonItem =
          UIBarButtonItem(barButtonSystemItem: .Add,
          target: self, 
          action:
            #selector(ViewController.addBtnAction))
    } else {
        // 顯示編輯完成按鈕
        self.navigationItem.leftBarButtonItem =
          UIBarButtonItem(barButtonSystemItem: .Done,
            target: self,
            action:
              #selector(ViewController.editBtnAction))

        // 隱藏新增按鈕
        self.navigationItem.rightBarButtonItem = nil
    }
}

上述程式根據 UITableView 的屬性editing來判斷目前是否處於編輯模式,並使用方法setEditing(_:animated:)來切換。切換的同時也一併設置新的左右兩邊的按鈕,只有非編輯模式時才有新增的按鈕。

要設置每筆 row 是否可以進入編輯模式,必須實作以下這個委任方法:

// 各 cell 是否可以進入編輯狀態 及 左滑刪除
func tableView(tableView: UITableView,
  canEditRowAtIndexPath indexPath: NSIndexPath) 
  -> Bool {
    return true
}

你可以根據 indexPath 來讓特定的 section 的 row 不能編輯。

新增一筆資料

在非編輯模式時,可以按導覽列右邊按鈕新增一筆資料,如下:

// 按下新增按鈕時執行動作的方法
func addBtnAction() {
    print("新增一筆資料")
    info.insert("new row", atIndex: 0)

    // 新增 cell 在第一筆 row
    myTableView.beginUpdates()
    myTableView.insertRowsAtIndexPaths(
      [NSIndexPath(forRow: 0, inSection: 0)],
      withRowAnimation: .Fade)
    myTableView.endUpdates()
}

上述程式先為示範的陣列新增一筆資料,再在 UITableView 的兩個方法beginUpdates()endUpdates()中間使用方法insertRowsAtIndexPaths(_:withRowAnimation:)新增一筆資料。

排序切換位置

必須實作下面這個委任方法,才會出現排序功能:

// 編輯狀態時 拖曳切換 cell 位置後執行動作的方法
// (必須實作這個方法才會出現排序功能)
func tableView(tableView: UITableView,
  moveRowAtIndexPath sourceIndexPath: NSIndexPath,
  toIndexPath destinationIndexPath: NSIndexPath) {
    print("\(sourceIndexPath.row) to")    
    print("\(destinationIndexPath.row)")

    var tempArr:[String] = []

   if(sourceIndexPath.row > destinationIndexPath.row) 
    { // 排在後的往前移動
        for (index, value) in info.enumerate() {
            if index < destinationIndexPath.row 
              || index > sourceIndexPath.row {
                tempArr.append(value)
            } else if 
              index == destinationIndexPath.row {
            tempArr.append(info[sourceIndexPath.row])
            } else if index <= sourceIndexPath.row {
                tempArr.append(info[index - 1])
            }
        }
    } else if (sourceIndexPath.row < 
      destinationIndexPath.row) { 
      // 排在前的往後移動
        for (index, value) in info.enumerate() {
            if index < sourceIndexPath.row 
            || index > destinationIndexPath.row {
                tempArr.append(value)
            } else if 
            index < destinationIndexPath.row {
                tempArr.append(info[index + 1])
            } else if 
            index == destinationIndexPath.row {
            tempArr.append(info[sourceIndexPath.row])
            }
        }
    } else {
        tempArr = info
    }

    info = tempArr
    print(info)

}

上述程式除了重新排序 UITableView 之外,也必須將示範的陣列重新排序。

刪除資料

編輯模式下刪除或是左滑刪除時,會執行以下方法:

// 編輯狀態時 按下刪除 cell 後執行動作的方法 
// (另外必須實作這個方法才會出現左滑刪除功能)
func tableView(tableView: UITableView,
  commitEditingStyle editingStyle:
  UITableViewCellEditingStyle, forRowAtIndexPath
  indexPath: NSIndexPath) {
    let name = info[indexPath.row]

    if editingStyle == .Delete {
        info.removeAtIndex(indexPath.row)

        tableView.beginUpdates()
        tableView.deleteRowsAtIndexPaths(
          [indexPath], withRowAnimation: .Fade)
        tableView.endUpdates()

        print("刪除的是 \(name)")
    }

}

除了刪除 UITableView 的資料外,也必須刪除示範陣列所屬的值。

以上即為本小節的示範內容。

範例

本小節範例程式碼放在 apps/todo

results matching ""

    No results matching ""