iT邦幫忙

2025 iThome 鐵人賽

DAY 22
0
Mobile Development

Swift iOS 開發新手村:從入門到 AI 聊天室系列 第 22

Day 22|Xcode 互動進階:點擊編輯留言,動態更新列表

  • 分享至 

  • xImage
  •  

昨天我們打造了一個簡易留言板,成功實現了新增留言的功能。但一個只能新增、不能修改的 App 還不夠完整!

今天,我們就要為這個專案進行關鍵升級,加入編輯與刪除兩大核心功能,讓它從一個簡單的練習,進化成一個功能齊全的實用工具。

我們將實作:

1.點擊編輯:點擊列表中的任一則留言,內容會自動回填至輸入框,方便使用者修改。
2.滑動刪除:使用者可以透過優雅的左滑手勢,快速刪除不需要的留言。

準備好讓你的 App 變得更強大、更完整了嗎?

今日學習重點

  • 實作點擊編輯:學習如何透過 didSelectRowAt 偵測點擊,並將資料回填至輸入框
  • 狀態管理:使用可選型別 (Int?) 追蹤編輯狀態,判斷是「新增」還是「更新」模式
  • 實作左滑刪除:掌握 UITableViewDataSource 的相關方法,實現滑動刪除功能
  • 精準更新 UI:學習使用 insertRowsreloadRowsdeleteRows 來實現帶有動畫的列表刷新

程式碼實作

功能規劃

  • 增加變數 editingIndex 紀錄編輯狀態與目前編輯留言索引
  • 點擊留言時,帶回資料至 TextField 並設定編輯狀態
  • 送出按鈕根據是否編輯狀態,執行更新或新增
  • 實作左滑刪除功能,從資料陣列刪除指定留言並更新介面
  • 刪除留言時,需同步處理編輯狀態,避免編輯錯亂

步驟1:宣告變數追蹤編輯狀態

先新增一個變數,用來記錄目前是否在編輯,以及目前正在編輯哪筆留言:

var editingIndex: Int? = nil

步驟2:帶資料回輸入框,設定編輯索引

修改 didSelectRowAt 內容,當用戶點擊留言時,會將文字帶回 TextField 並記錄索引:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    editingIndex = indexPath.row
    txfMessage.text = messages[indexPath.row]
    print("你點了第 \(indexPath.row + 1) 筆留言:\(messages[indexPath.row])")
        
    tableView.deselectRow(at: indexPath, animated: true)
}

步驟3:修改送出按鈕動作:判斷新增或更新

按送出時,有編輯索引就更新留言,否則新增留言:

@IBAction func didTapButton(_ sender: UIButton) {
    guard let text = txfMessage.text?.trimmingCharacters(in: .whitespacesAndNewlines), !text.isEmpty else {
        return
    }
        
    if let index = editingIndex {
        messages[index] = text
        editingIndex = nil
    } else {
        messages.append(text)
    }
        
    tbvMessage.reloadData()
    txfMessage.text = ""
}

步驟4:加入 UI 提示,動態切換送出按鈕文字(非必要)

viewDidLoad() 中初始化按鈕文字為「送出」:

override func viewDidLoad() {
    super.viewDidLoad()
        
    btnEnter.setTitle("送出", for: .normal)
        
    let nib = UINib(nibName: "MainTableViewCell", bundle: nil)
    tbvMessage.register(nib, forCellReuseIdentifier: "MainTableViewCell")
        
    tbvMessage.dataSource = self
    tbvMessage.delegate = self
    }

修改 didTapButton,在編輯結束時將按鈕文字恢復成「送出」:

@IBAction func didTapButton(_ sender: UIButton) {
    guard let text = txfMessage.text?.trimmingCharacters(in: .whitespacesAndNewlines), !text.isEmpty else {
        return
    }
        
    if let index = editingIndex {
        messages[index] = text
        editingIndex = nil
        btnEnter.setTitle("送出", for: .normal)
    } else {
        messages.append(text)
    }
        
    tbvMessage.reloadData()
    txfMessage.text = ""
    }

同時在 didSelectRowAt 中,切換按鈕文字為「更新」:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    editingIndex = indexPath.row
    txfMessage.text = messages[indexPath.row]
    btnEnter.setTitle("更新", for: .normal)
    print("你點了第 \(indexPath.row + 1) 筆留言:\(messages[indexPath.row])")
    
    tableView.deselectRow(at: indexPath, animated: true)
}

步驟5:實現左滑刪除

UITableViewDataSourceUITableViewDelegate 中新增以下程式碼,實作左滑刪除留言:

// 允許 TableView 支援編輯(刪除)
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
}

// 編輯左滑刪除的動作
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        // 移除資料
        messages.remove(at: indexPath.row)
        
        // 如果目前正在編輯的留言被刪除了,清除 editingIndex
        if let editing = editingIndex, editing == indexPath.row {
            editingIndex = nil
            btnEnter.setTitle("送出", for: .normal)
            txfMessage.text = ""
        } else if let editing = editingIndex, editing > indexPath.row {
            // 若 editingIndex 在刪除列的後方,刪除後要往前移一格
            editingIndex = editing - 1
        }
            
        // 刪除該列動畫
        tableView.deleteRows(at: [indexPath], with: .automatic)
    }
}

執行後會發現左滑刪除的按鈕文字是 Delete,如果想改成其他文字,可以再加上一段程式:

// 自訂左滑刪除按鈕文字
func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
    return "刪除" // 可以改成你想要顯示的文字
}

步驟6:執行測試

輸入留言,點擊送出,留言會新增並顯示在列表:

https://ithelp.ithome.com.tw/upload/images/20251006/20177542G2lvsqSeDy.png
點擊任一筆留言,該留言會帶回輸入框,送出按鈕變成「更新」:

https://ithelp.ithome.com.tw/upload/images/20251006/201775421LPmagpxKH.png
修改留言內容,點擊「更新」按鈕,該筆留言會被更新,列表立即刷新:

https://ithelp.ithome.com.tw/upload/images/20251006/20177542XYmzDCOGFj.png
嘗試左滑刪除任一筆留言:

https://ithelp.ithome.com.tw/upload/images/20251006/20177542KvgqIx9LEy.png
按下「刪除」鍵後,該留言就能成功被刪除:

https://ithelp.ithome.com.tw/upload/images/20251006/20177542dNlJph7yLL.png
如果能成功執行到這邊,代表在程式撰寫方面已經順利完成啦!

小結一下

今天,我們成功地為留言板加上了編輯與刪除兩大核心功能,讓它從一個簡單的展示工具,升級為一個功能完整的應用!

我們透過 editingIndex 這個「狀態旗標」,巧妙地讓同一個按鈕能處理新增與更新兩種不同邏輯。更重要的是,你學會了 TableView 中新增 (insertRows)、更新 (reloadRows) 與刪除 (deleteRows) 的精準動畫操作,這讓 App 的使用者體驗提升了一個檔次。

掌握這些技巧,你已經可以為任何列表型資料加上完整的編輯與刪除功能,讓 App 互動性大幅提升。

🌟 明日預告

隨著我們的 App 功能越來越多,程式碼是不是開始變得像一團打結的毛線,不知道該把新功能寫在哪?

明天,我們要從「寫程式」升級為「設計架構」!我們將學習 iOS 開發中最經典的設計模式:MVC(Model-View-Controller)。你可以把它想像成經營一家餐廳:

  • Model (模型):廚房裡的食材與食譜(你的資料)。
  • View (視圖):餐廳的裝潢與餐盤(使用者看到的畫面)。
  • Controller (控制器):忙碌的服務生(協調一切的邏輯中樞)。

學會 MVC,你就能讓程式碼各司其職、井然有序,為未來打造大型、可維護的 App 奠定最重要的基礎!

敬請期待《Day 23|Xcode 架構教學:掌握 MVC 設計模式》


上一篇
Day 21|Xcode 列表入門:資料一覽無遺,實戰 TableView
下一篇
Day 23|Xcode 架構教學:掌握 MVC 設計模式
系列文
Swift iOS 開發新手村:從入門到 AI 聊天室24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言