iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0
Mobile Development

我將成為Swift之強者系列 第 18

Day18 - 仿刻 iOS 鬧鐘實作:新增與編輯鬧鐘(上)

  • 分享至 

  • xImage
  •  

Day18 - 仿刻 iOS 鬧鐘實作:新增與編輯鬧鐘(上)

在這一篇中,我們要來介紹 AddAlarmViewController 的上半部分,包含 畫面初始化、UI 設定、鬧鐘儲存與更新,並透過程式碼一步步拆解。


1. 導入套件與協議設計

import UIKit
import RealmSwift

protocol AddAlarmViewControllerDelegate: AnyObject {
    func didAddNewAlarm()
    func didUpdateAlarm()
    func didDeleteAlarm()
}
  • UIKit:UI 元件使用。
  • RealmSwift:資料庫存取。
  • Delegate Protocol:新增、更新、刪除鬧鐘時,通知主畫面刷新。

2. 主要屬性設定

class AddAlarmViewController: UIViewController, UITextFieldDelegate {
    
    @IBOutlet weak var DatePicker: UIDatePicker!
    @IBOutlet weak var tbvAddAlarm: UITableView!
    @IBOutlet weak var btnDelete: UIButton!
    
    weak var delegate: AddAlarmViewControllerDelegate?
    var repeatDays: [Bool] = Array(repeating: false, count: 7)
    var selectedSound: String = ""
    var alarmname: String = ""
    var alarmToEdit: AlarmData?
    var snoozeEnabled: Bool = true
  • repeatDays:一週 7 天的布林陣列,決定哪些天要重複。
  • alarmToEdit:判斷是否進入編輯模式。
  • selectedSound、alarmname、snoozeEnabled:提示聲、鬧鐘名稱、稍後提醒的設定值。

3. ViewDidLoad 與 UI 初始化

override func viewDidLoad() {
    super.viewDidLoad()
    tbvAddAlarm.delegate = self
    tbvAddAlarm.dataSource = self
    tbvAddAlarm.register(UINib(nibName: "AddAlarmTableViewCell", bundle: nil), forCellReuseIdentifier: "AddAlarmTableViewCell")
    setUI()
    setupTextFieldDelegate()
    
    if let alarm = alarmToEdit, !alarm.isInvalidated {
        repeatDays = Array(alarm.repeatDays)
        selectedSound = alarm.sound
        alarmname = alarm.name
        snoozeEnabled = alarm.snoozeEnabled
        if let date = formatStringToDate(alarm.alarmTime) {
            DatePicker.date = date
        }
    }
}
  • 設定 TableView 資料來源與委派
  • 註冊自訂 Cell。
  • 若是編輯模式,會將資料回填。

4. UI 設定與操作按鈕

func setUI() {
    DatePicker.locale = Locale(identifier: "zh_TW")
    title = alarmToEdit == nil ? "加入鬧鐘" : "編輯鬧鐘"
    navigationItem.rightBarButtonItem = UIBarButtonItem(title: "儲存", style: .plain, target: self, action: #selector(doneTapped))
    navigationItem.leftBarButtonItem = UIBarButtonItem(title: "取消", style: .plain, target: self, action: #selector(cancelTapped))
    
    btnDelete.isHidden = alarmToEdit == nil
    btnDelete.setTitle("刪除鬧鐘", for: .normal)
    btnDelete.setTitleColor(.red, for: .normal)
    btnDelete.addTarget(self, action: #selector(deleteTapped), for: .touchUpInside)
}
  • 新增模式會隱藏刪除按鈕。
  • 編輯模式會顯示刪除按鈕。

5. 儲存、更新與刪除鬧鐘

儲存新鬧鐘

func saveNewAlarm() {
    let realm = try! Realm()
    let newAlarm = AlarmData(
        alarmTime: formatDate(DatePicker.date),
        creatTime: getSystemTime(),
        name: alarmname,
        repeatDays: repeatDays,
        sound: selectedSound,
        snoozeEnabled: snoozeEnabled
    )
    try! realm.write { realm.add(newAlarm) }
    scheduleNotification(for: newAlarm)
    delegate?.didAddNewAlarm()
    self.dismiss(animated: true, completion: nil)
}

更新已存在鬧鐘

func updateAlarm(_ alarm: AlarmData) {
    let realm = try! Realm()
    try! realm.write {
        alarm.alarmTime = formatDate(DatePicker.date)
        alarm.name = alarmname.isEmpty ? "鬧鐘" : alarmname
        alarm.repeatDays.removeAll()
        alarm.repeatDays.append(objectsIn: repeatDays)
        alarm.sound = selectedSound
        alarm.snoozeEnabled = snoozeEnabled
    }
    scheduleNotification(for: alarm)
    delegate?.didUpdateAlarm()
    self.dismiss(animated: true, completion: nil)
}

刪除鬧鐘

@objc func deleteTapped() {
    guard let alarm = alarmToEdit else { return }
    let realm = try! Realm()
    try! realm.write { realm.delete(alarm) }
    delegate?.didDeleteAlarm()
    self.dismiss(animated: true, completion: nil)
}

到這裡,我們已經完成 UI 初始化基本資料操作(新增、更新、刪除)
下一篇(Day19)將介紹 TableView 顯示、頁面跳轉、通知排程與 Delegate 回傳


上一篇
Day17 - 仿刻 iOS 鬧鐘實作:MainTableViewCell 介紹
系列文
我將成為Swift之強者18
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言