規劃與實作
請先在 Xcode 打開這個專案( apps/todo/Todo )以供後續與文章內容比對檢視,本小節說明僅會提示部分內容,不會將所有程式碼都寫出來,請以專案程式碼為主。
首先介紹待辦事項應用程式可以操作的動作,先看下圖流程:
上圖從 Main 為首頁開始,依序可以操作如下的動作:
- 新增:在首頁第一行輸入事項文字,點擊右邊的加號,即可新增事項。
- 列表與編輯:待辦事項會列在首頁下方,點擊項目可以修改事項文字。可以點擊各筆項目右邊的確認框打勾以完成事項。
- 排序或刪除:點擊首頁左上角編輯,可以為事項排序或是刪除事項。
- 關於:點擊首頁右上角關於,可以進入關於頁。可以檢視已完成事項、關閉或開啟音效(新增、打勾、刪除事項時的音效)、前往支援網頁與來源網頁。
- 已完成事項:打勾的已完成事項會列在這頁,你也可以再次點擊確認框來取消完成,事項會回到首頁列表,或是也可左滑刪除這個事項(首頁列表也可以左滑刪除)。
前置作業
首先在 Xcode 裡,新建一個 Single View Application 類型的專案,取名為 ToDo 。
這個專案會使用 Core Data 來儲存與操作資料,所以建立專案的過程中,請記得將Use Core Data
打勾,如下圖:
接著請依照 Core Data 的內容依序建立需要的檔案與功能, Entity 取名為 Record ,以及建立四個 Attributes ,如下圖示:
上述 Core Data 設定完後,專案應該新增好下列檔案:
- Record+CoreDataProperties.swift
- Record.swift
- CoreDataConnect.swift
在寫程式碼之前,先依照程式之外的設定的步驟設定好。以及將需要的 Swift 檔案、圖示檔案、音效檔案都先加入至專案中:
- BaseViewController.swift
- MoreViewController.swift
- ChechedRecordsViewController.swift
- icons 目錄中的三個圖示檔案
- sounds 目錄中的四個音效檔案
AppDelegate.swift
在進入應用程式的畫面前,需要在 AppDelegate.swift 中先做些設定:
- 在 NSUserDefaults 中儲存是否開啟音效的值,以供後續使用與更新。
- 設置導覽列的一些預設樣式。
- 依照導覽控制器 UINavigationController 的說明,將根視圖設為一個 UINavigationController ,並指定 ViewController 為第一個視圖控制器。
首頁
因為首頁 ViewController 與已完成事項頁 ChechedRecordsViewController 要做的事情差不多,所以將重複的功能都寫在一個繼承自 UIViewController 的 BaseViewController ,並讓兩者都再繼承自他,這樣重複的功能便不用寫兩遍。
BaseViewController.swift
先注意以下 BaseViewController 的幾個屬性:
- 建立屬性
checkStatus
來辨別目前執行動作的是首頁還是已完成事項頁。 - 建立陣列屬性
myRecords
存放取得的事項列表,在 UITableView 的委任方法中,則是直接對這個陣列做操作。 - 建立屬性
cehckTagTemp
用來幫助設置每個確認框所代表的事項資訊。
viewDidLoad()
在viewDidLoad()
方法中,先連接 Core Data 與設置基本設定。因為其他頁的設定改變,可能導致這頁的內容會有所不同,所以大多的功能是寫在viewWillAppear()
方法裡()。
viewWillAppear()
在viewWillAppear()
方法中,先確認音效是否開啟,接著取得事項列表(使用屬性checkStatus
來辨別是首頁還是已完成事項頁),最後依據是否開啟音效來設置播放器或是設為nil
。(請參考後續小節播放音效的介紹。)
UITableView 的委任方法
tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
方法是用來顯示每筆事項的內容,在前面章節介紹 UITableView 時可以得知 UITableViewCell 是重複使用的,所以要注意先將內部的 UIButton 移除,才不會出現非預期中的按鈕,如下:
// 移除舊的按鈕
for view in cell.contentView.subviews {
if let v = view as? UIButton {
v.removeFromSuperview()
}
}
接著才依照屬性checkStatus
加上勾選確認框的 UIButton 。
按下按鈕執行動作的方法
checkBtnAction(_:)
方法是負責按下事項打勾確認框時的動作,會先依照 UIButton 的 tag 來找出這筆事項的 id ,再作打勾或取消打勾的動作,這邊可以注意到沒有依據音效是否開啟來播放音效,如下:
// 音效
doneSound?.play()
因為在稍前viewWillAppear()
方法中,已設置成播放器或 nil ,當設為 nil 時是不會發生任何事,所以只要寫上面這樣即可。
ViewController.swift
繼承自 BaseViewController 的 ViewController 只需要再將新增事項的部份加上就差不多了。
viewDidLoad()
首先設置屬性checkStatus
為false
,表示這頁的列表是待辦事項。接著依序建立 UITableView 、前往更多頁面按鈕、新增事項輸入框及按鈕。
viewWillAppear()
使用super.viewWillAppear(true)
來執行父類別中的動作。接著為了每次到這頁時都確實不會是 UITableView 的編輯模式,所以會執行下列程式:
// 進入 非 編輯模式
myTableView.setEditing(true, animated: false)
self.editBtnAction()
按下按鈕執行動作的方法
editBtnAction()
方法是負責按下左上編輯按鈕時的動作,除了切換自身按鈕的樣式外,還要切換新增事項輸入框的開放與限制和每筆事項的打勾確認框顯示與隱藏。
addBtnAction()
方法負責新增事項的動作,這邊加上一個沒有填入文字時無法新增的限制。
UITableView 的委任方法
UITableView 可以使用setEditing(_:, animated:)
方法來切換編輯模式。
在編輯模式時,tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath)
方法用來執行排序後的動作,更多內容請參考 UITableView 的編輯模式。
其他方法
點擊列表中的事項會執行updateRecordContent(_:)
方法來編輯事項內容,這部份使用 UIAlertController 跳出一個提示框來編輯。
更多 頁面
這頁使用 UITableView 的 .Grouped 特性各別列出不同的功能:
- 前往已完成事項頁面。
- 使用 UISwitch 元件來開關音效。
- 前往外部 Facebook 網頁。
- 前往外部 音效資源 網頁。
前往外部網頁時,使用下列方式:
let requestUrl = NSURL(string:
"https://www.facebook.com/1640636382849659")
UIApplication.sharedApplication().openURL(requestUrl!)
已完成事項 頁面
繼承自 BaseViewController 的 ChechedRecordsViewController 其實功能很簡單,首先設置屬性 checkStatus 為 true ,表示這頁的列表是已完成事項,再將 UITableView 設置完成。其餘的事已經在 BaseViewController 都做完了。
範例
此應用程式範例程式碼放在 apps/todo/Todo
你也可以在 App Store 中找到這個應用程式,名稱為待辦事項 。