iT邦幫忙

2024 iThome 鐵人賽

DAY 23
0
Mobile Development

少年K的Swift奇幻漂流記系列 第 23

Day23 Swift Clock App 實作 Part4:tableView顯示內容

  • 分享至 

  • xImage
  •  

這段程式碼展示了如何使用 UITableView 來顯示資料,並包括了刪除功能、進入編輯模式等功能。以下是排版過後的程式碼,並附上註解解釋每個部分的功能。

MainViewController TableView Delegate 和 DataSource

extension MainViewController: UITableViewDelegate, UITableViewDataSource {
    
    // 設定tableView有幾個section
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    // 設定每個section裡有多少row
    func tableView(_ tableView: UITableView, 
                   numberOfRowsInSection section: Int) -> Int {
        // 根據新增的鬧鐘數量決定有多少row
        return alarms.count
    }
    
    // 設定tableView每個cell要顯示的內容
    func tableView(_ tableView: UITableView, 
                   cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: SecondTableViewCell.identifier, 
        for: indexPath) as! SecondTableViewCell
        
        // 取得每一個row對應的鬧鐘資料
        let alarm = alarms[indexPath.row]
        
        // 在cell裡顯示鬧鐘的時間和名稱
        cell.lbList.text = alarm.alarmTime
        cell.lbName.text = alarm.name.isEmpty ? "鬧鐘" : alarm.name
        
        // 設定鬧鐘的開關
        cell.swAlarm.isOn = alarm.isEnabled
        cell.swAlarm.tag = indexPath.row // 儲存開關對應的row
        cell.swAlarm.addTarget(self, 
                               action: #selector(alarmSwitchChange(_:)), 
                               for: .valueChanged)
        
        // 如果在編輯模式中,隱藏開關
        cell.swAlarm.isHidden = isEditing
        
        // 加入可以點選進行編輯的樣式
        cell.accessoryType = .disclosureIndicator
        return cell
    }
    
    // 處理點選某一個row的動作
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // 允許該section的row被選擇
        tableView.allowsSelection = true
        tableView.deselectRow(at: indexPath, animated: true)
        
        // 取得選擇的鬧鐘
        let alarm = alarms[indexPath.row]
        let editAlarmVC = AddAlarmViewController(nibName: "AddAlarmViewController", bundle: nil)
        
        // 將選中的鬧鐘資料傳遞到編輯頁面
        editAlarmVC.alarmToEdit = alarm
        editAlarmVC.selectedSound = alarm.sound
        editAlarmVC.delegate = self
        
        // 顯示編輯頁面
        let navController = UINavigationController(rootViewController: editAlarmVC)
        self.present(navController, animated: true, completion: nil)
    }
    
    // 處理進入編輯模式後刪除row的動作
    func tableView(_ tableView: UITableView, 
                   commit editingStyle: UITableViewCell.EditingStyle, 
                   forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            // 根據是否開啟過濾鬧鐘
            let filteredAlarms = alarms.filter { 
                indexPath.section == 0 ? $0.isEnabled : !$0.isEnabled 
            }
            let alarm = filteredAlarms[indexPath.row]
            deleteAlarm(alarm, at: indexPath)
        }
    }
    
    // 左滑刪除的功能
    func tableView(_ tableView: UITableView, 
    trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> 
    UISwipeActionsConfiguration? {
    
        let deleteAction = UIContextualAction(style: .destructive, title: "刪除") { 
            [weak self] (_, _, completionHandler) in
            
            guard let self = self else { return }
            
            // 過濾鬧鐘
            let filteredAlarms = self.alarms.filter { 
                indexPath.section == 0 ? $0.isEnabled : !$0.isEnabled
            }
            let alarm = filteredAlarms[indexPath.row]
            self.deleteAlarm(alarm, at: indexPath)
            completionHandler(true)
        }
        
        // 設定刪除按鈕背景顏色
        deleteAction.backgroundColor = .red
        
        return UISwipeActionsConfiguration(actions: [deleteAction])
    }
}

刪除鬧鐘功能

func deleteAlarm(_ alarm: AlarmData, at indexPath: IndexPath) {
    let realm = try! Realm()

    // 刪除鬧鐘相關的通知
    UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [alarm.creatTime])
    
    for index in 0..<7 {
        UNUserNotificationCenter.current().removePendingNotificationRequests(
            withIdentifiers: ["\(alarm.creatTime)_\(index)"]
        )
    }
    
    // 刪除Realm資料庫中的鬧鐘
    try! realm.write {
        realm.delete(alarm)
    }
    
    // 移除alarms中的鬧鐘並更新tableView
    alarms.remove(at: indexPath.row)
    tableView.deleteRows(at: [indexPath], with: .fade)
}

說明

  1. 顯示內容:使用 UITableViewnumberOfSectionsnumberOfRowsInSection 來控制有多少個 section 和 row。每個 row 的內容在 cellForRowAt 中設定。
  2. 選擇資料動作:使用 didSelectRowAt 方法來監聽使用者選擇的行,並打開編輯頁面。
  3. 進入編輯模式:在 commit editingStyle 中處理刪除動作,並搭配 Realm 刪除鬧鐘資料。
  4. 左滑刪除功能:使用 trailingSwipeActionsConfigurationForRowAt 方法來啟用左滑刪除。

接下來的文章將教如何新增鬧鐘和設置通知功能。


上一篇
Day22 Swift Clock App 實作 Part3:建立鬧鐘需要的模型
下一篇
Day24 Swift Clock App 實作 Part5:請求通知功能權限
系列文
少年K的Swift奇幻漂流記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言