[Swift]Day18&19:一個(gè)簡(jiǎn)單的例子
來(lái)源:程序員人生 發(fā)布時(shí)間:2014-12-09 08:10:33 閱讀次數(shù):4390次
Swift90Days - 1個(gè)簡(jiǎn)單的小利用
第0步:明確任務(wù)
經(jīng)過(guò)前面基礎(chǔ)語(yǔ)法的學(xué)習(xí),我們終究可以真槍實(shí)彈的來(lái)1發(fā)了。以這篇小雞雞小貓貓小狗狗為例,我們將會(huì)創(chuàng)建1個(gè)簡(jiǎn)單的利用:
- 通過(guò)
UITableView
展現(xiàn)3種小動(dòng)物
- 通過(guò)
NSUserDefaults
進(jìn)行數(shù)據(jù)持久化
- 通過(guò)
UIWebView
從維基百科加載更多數(shù)據(jù)
由于時(shí)間有限,這篇博客其實(shí)不是教程或翻譯,只是1個(gè)關(guān)鍵思路的整理和記錄,完全的源代碼在文末有鏈接,如果有任何疑問(wèn)歡迎與我聯(lián)系,謝謝。
第1步:創(chuàng)建項(xiàng)目
創(chuàng)建1個(gè)新的項(xiàng)目,模板選擇 Single View Application
,項(xiàng)目名稱(chēng)叫做:BirdsCatsDogs。
第2步:簡(jiǎn)單重構(gòu)
系統(tǒng)為我們自動(dòng)生成了 ViewController.swift
,將其改成SpeciesViewController.swift
,記得也改下類(lèi)的名字。然后在 StoryBoard (以后簡(jiǎn)稱(chēng)為 SB 希望不要誤解) 中設(shè)置 custum class
,如果設(shè)置正確在輸入的時(shí)候是有自動(dòng)補(bǔ)全的,回車(chē)便可。
第3步:添加導(dǎo)航
拖拽1個(gè) UINavigationController 到 SB 中,設(shè)置成 Initial View Controller
,然后把 SpeciesViewController
設(shè)置成它的 root view controller
。把 SpeciesViewController
的 title 設(shè)置成 Species
。
運(yùn)行1下,確保沒(méi)有問(wèn)題。(不可能有問(wèn)題,這時(shí)候候運(yùn)行1般是滿(mǎn)足自己內(nèi)心的成績(jī)感。)
第4步:加載數(shù)據(jù)
在這里我們用 NSUserDefaults
加載數(shù)據(jù),通常它用來(lái)存儲(chǔ)1些系統(tǒng)配置,比如字體大小啊之類(lèi)的。
我們新建1個(gè) DataManager.swift
,通過(guò)單例模式實(shí)現(xiàn)1個(gè)數(shù)據(jù)管理器:
import Foundation class DataManager { struct Static { static var onceToken : dispatch_once_t = 0 static var instance : DataManager? = nil } class var sharedInstance : DataManager { dispatch_once(&Static.onceToken) { Static.instance = DataManager() } return Static.instance! } }
這段代碼是原文的代碼,有些地方可以參考:
- 靜態(tài)變量通過(guò)內(nèi)嵌
Static
結(jié)構(gòu)體存儲(chǔ)。
- 單例模式通過(guò)
dispatch_once
實(shí)現(xiàn),通過(guò) sharedInstance
獲得。 (GCD的內(nèi)容后面再補(bǔ)充)
接下來(lái)我們?cè)?nbsp;DataManager
里面添加1個(gè)變量:species
,類(lèi)型為 [String:[String]]
。在 init()
里加上1些初始化的工作:
var species: [String:[String]] init() { let userDefaults = NSUserDefaults.standardUserDefaults() if let speciesInfo = userDefaults.valueForKey("species") as? [String:[String]] { species = speciesInfo } else { species = [ "Birds": ["Swift"], "Cats" : ["Persian Cat"], "Dogs" : ["Labrador Retriever"] ] } }
我們可以通過(guò) DataManager.sharedInstance.species
獲得各個(gè)種類(lèi)的數(shù)據(jù)。
Tips:類(lèi)似于單例模式這類(lèi)可能會(huì)屢次用到的代碼片斷,建議加到 Xcode 的 Snippets 里。
第5步:加載列表
我們用字典存儲(chǔ)了數(shù)據(jù),通過(guò) key 值獲得數(shù)據(jù)10分方便。但是字典本身是無(wú)序的,而像 UITableView 這類(lèi)列表的數(shù)據(jù)本身是有序的。所以添加1個(gè)計(jì)算屬性 speciesList
,可以獲得排序以后的列表并返回:
var speciesList: [String] { var list: [String] = [] for speciesName in species.keys { list.append(speciesName) } list.sort(<) return list }
回到 SpeciesViewController
里,我們可以這樣獲得數(shù)據(jù):
var species: [String] = DataManager.sharedInstance.speciesList
第6步:列表視圖
拖拖拽拽設(shè)置好 UITableView
,具體進(jìn)程就不贅述了,可以直接打開(kāi)項(xiàng)目看看。tableview
相干的部份代碼以下:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell cell.textLabel?.text = species[indexPath.row] return cell } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return species.count }
運(yùn)行1下,確保沒(méi)有問(wèn)題。(這時(shí)候候就不是成績(jī)感的問(wèn)題了,測(cè)試 SB 和代碼的連接情況。)
第7步:詳情頁(yè)面
我們?cè)賱?chuàng)建1個(gè) RacesViewController
,用來(lái)展現(xiàn)當(dāng)前種類(lèi)下的數(shù)據(jù)列表:
class RacesViewController: UIViewController { var species: String! override func viewDidLoad() { super.viewDidLoad() title = species } }
注意在 StoryBoard 里設(shè)置這個(gè) RacesViewController
的 StoryBoard ID ,這樣我們?cè)谧鳇c(diǎn)擊事件的時(shí)候可以獲得到這個(gè) RacesViewController
然落后行 pushViewController
操作。
第8步:選中事件
回到 SpeciesViewController
里,添加單元格的選中事件:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { tableView.deselectRowAtIndexPath(indexPath, animated: true) var racesViewController = storyboard?.instantiateViewControllerWithIdentifier("RacesViewController") as RacesViewController racesViewController.species = species[indexPath.row] navigationController?.pushViewController(racesViewController, animated: true) }
instantiateViewControllerWithIdentifier
可以通過(guò) StoryBoard ID 初始化 ViewController 。
第9步:展現(xiàn)種類(lèi)
這個(gè)步驟和第6步基本相同, tableview
相干的代碼:
func tableView
(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return races.count } func tableView
(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(
"RaceCell") as UITableViewCell cell.textLabel?.text = races[indexPath.row] cell.
accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
return cell }
這時(shí)候再測(cè)試1下,點(diǎn)擊 cell 以后會(huì)跳轉(zhuǎn)到另外一個(gè)表格列表里。
第10步:保存修改
給 DataManager
加個(gè)添加的方法:
func saveData() { let userDefaults = NSUserDefaults.standardUserDefaults() userDefaults.setValue(species, forKey: "species") } func addRace(species inSpecies: String, race: String) { if var races = species[inSpecies] { races.append(race) species[inSpecies] = races } saveData() }
saveData
方法用來(lái)寫(xiě)入本地,addRace
方法供外部調(diào)用,添加1條記錄。
第11步:添加按鈕
給導(dǎo)航欄加個(gè) Add 按鈕,并且關(guān)聯(lián) didTapAdd
這個(gè) IBAction
。
第12步:彈出視圖
使用 UIAlerView
彈出視圖輸入內(nèi)容,注意設(shè)置 style 為 PlainTextInput
,設(shè)置 delegate 為 self 。
@IBAction func didTapAdd() { var alert = UIAlertView(title: "New Race", message: "Type in a new race", delegate: self, cancelButtonTitle: "Cancel", otherButtonTitles: "Add") alert.alertViewStyle = UIAlertViewStyle.PlainTextInput alert.show() }
然后實(shí)現(xiàn) alertView
的拜托方法:
func alertView(alertView: UIAlertView, didDismissWithButtonIndex buttonIndex: Int) { if buttonIndex == 1 { var textField = alertView.textFieldAtIndex(0)! var newRace = textField.text DataManager.sharedInstance.addRace(species: species, race: newRace) var newIndexPath = NSIndexPath(forRow: races.count - 1, inSection: 0) myTableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: UITableViewRowAnimation.Automatic) } }
這個(gè)時(shí)候再運(yùn)行1下測(cè)試1下添加功能是否是OK。
第13步:刪除數(shù)據(jù)
和添加數(shù)據(jù)1樣,我們先去 DataManager 加個(gè)刪除數(shù)據(jù)的方法:
func removeRace(species inSpecies: String, race inRace: String) { if var races = species[inSpecies] { var index = -1 for (idx, race) in enumerate(races) { if race == inRace { index = idx break } } if index != -1 { races.removeAtIndex(index) species[inSpecies] = races saveData() } } }
有幾個(gè)值得注意的地方:
- 通過(guò)
index
設(shè)置為 ⑴ 作為標(biāo)識(shí),避免出現(xiàn)搜索到最后也沒(méi)找到的結(jié)局。
- 通過(guò)
enumerate
來(lái)遍歷數(shù)組,既不用 ++i
式的遍歷,又可以獲得索引值。
然后回到 RacesViewController
,添加刪除相干的拜托方法:
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { return true } func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { var raceToRemove = races[indexPath.row] DataManager.sharedInstance.removeRace(species: species, race: raceToRemove) tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) }
試1下刪除操作,OK沒(méi)問(wèn)題。
完結(jié)
后面 WebView 的內(nèi)容沒(méi)甚么亮點(diǎn),大同小異,不再記錄。
匆匆記錄了1些關(guān)鍵點(diǎn),如果想完全學(xué)習(xí)請(qǐng)參考援用中的教程。
其實(shí)全部項(xiàng)目的功能很簡(jiǎn)單,不過(guò)湊頭到尾走1遍可以體驗(yàn)1下其他程序員的開(kāi)發(fā)思路和基本步驟。總之還是有些收獲的。不過(guò)邊看邊記錄效力太低,以后只會(huì)記錄關(guān)鍵的收獲,不再
生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)