Swift - TableViewCell deletion programmatically

前言:

大學畢業了,在前往研究所之路的過渡期,雖然心裡想著這是我最後一個暑假,應該要好好玩、大力玩,但是心裡總有一點聲音在警惕自己不要虛度這年輕寶貴的時刻,所以老樣子,承襲每年放寒暑假的傳統,self-learning iOS is still my main task to do !

其實以往都有在持續(或是說斷斷續續)跟Swift培養感情,但是礙於自己蠻懶的,一方面學的比較沒那麼積極、一方面部落格也就沒什麼在寫,所以趁現在剛學到一個新概念,趕緊花時間記錄下來,至於今天的主題也寫在標題上了,要來紀錄如何用手刻(programmatically)讓UITableViewCell從UITableView進行刪除的動作。
這也是我第一次用刻UI的方式做整個小專案的練習,以前Storyboard用久了,順便利用這個暑假學習純code來開發一個app。
而今天的教學資源來自Let's build that app這個頻道的這個影片中的一部份實作內容,我follow這個頻道也算蠻久了,無聊就會找這個講師的影片配飯看、照三餐看(誤),我只能說這個講師非常厲害,好啦,廢話不多說,我們趕快開始吧!

正文:

首先,請到我的Github下載原始專案:

打開之後,修改一下Identity,並執行:

可以看到已經有3列的cell,且每個cell除了有顯示label name (item 1, item 2, item 3),還各自有一個delete按鈕,我們要做的就是在按下delete之後,會將對應列的cell刪除。

沒有問題後,我們要建立一個刪除UITableViewCell的動作,所以我們寫一個函式在MyTableViewController的class內:



至於要在MyCell執行deleteCell()要怎麼做?很簡單,只要在MyCell給定一個MyTableViewController的變數,先將其設為Optional:

修改MyCell裡的handleAction():
將print("tapped")刪除,並加入

用來刪除自己(參數帶入self)

這樣就完成了嗎?不!
你可以在myTableViewController?.deleteCell(cell: self)設下breakpoint,並執行。


接著在模擬器或實機按下cell旁的delete按鈕,可以在debug area看到myTableViewController的值為nil:


Why? 因為我們在
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let myCell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! MyCell
        myCell.nameLabel.text = items[indexPath.row]
        return myCell
    }
這個函式內,沒有賦值給myCell裡的myTableViewController變數,所以修改tableView(_:, cellForRowAt:)這個函式裡的內容:


接著要驗證按下Delete按鈕後,控制流程是否正確,我們先移除剛剛handleAction()的breakpoint,接著在deleteCell()處設下中斷點,並執行。
然後按下模擬器或實機上cell的Delete按鈕,如果會出現下圖這樣正常觸發,恭喜你,目前為止大致做對了!

下一步是要呼叫刪除特定列的函式。我們在deleteCell()函式內呼叫這樣的一個函式:

至於參數的傳入,根據Apple Developer Documentation對此一函式的說明文件:
好的,現在就要來給定刪除的索引列,至於要取得當前刪除的列,我們可以用indexPathForCell()這個函式取得當前列,故將整個deleteCell()函式修改如下:

接著執行看看。
.
.
咦?怎麼crash了
不對呀,我刪除的函式有被呼叫到,也沒有丟錯參數,怎麼會錯呢?

哦! 我想到了

我刪除某一列的時候,那整個TableView的Cell內容是不是就也要跟著刪除?
是的,當我們執行上面的deleteRows()之後,事實上只剩下2個cell可以顯示內容,而我們最初的items共有3個項目(也就是第13行建立的items陣列),3個項目怎麼可以塞進2個cell呢?當然不行啊,況且我的目的是要連同cell的內容一併刪除,所以要在deleteRows()執行之前,先找出items陣列欲刪除的某一筆資料,換句話說就是要刪除某一cell所對應的items陣列索引內的某一筆資料,故我們要再次修改deleteCell()函式內容如下:

再執行一次,是不是可以順利刪除資料了呢?

可以的話,恭喜你學到一課 Woh~ nice !

留言

這個網誌中的熱門文章

Windows 10 64bits安裝Spyder (Anaconda)

在Spyder IDE 使用Python + OpenCV

Raspberry Pi - 利用AnyDesk遠端到樹莓派,並保持螢幕解析度不縮放