單字App

倒數第二堂課的課堂實作 ,回家給APP穿新衣並完善其功能 。

先把peter提供的各個單字txt檔丟入專案資料夾中 ,因為缺了X的檔案,所以我自己隨便編寫了一個放進去 。

然後建立三個class檔案分別為 :字母按鈕列表頁的mainViewController 、英文頁面的EnglishViewController跟中文頁面的ChineseViewController 。

拉出三個View Controller頁面:字母按鈕列表頁 、英文頁 、中文頁 ,並在"字母按鈕列表頁"跟"中文頁"前面插入Navigation Controller。

接著將26個字母按鈕拉segue(show)連線到EnglishViewController。

EnglishViewController(英文頁面)右上角的"中文"按鈕 ,拉segue(Present Modally)到中文頁前面的Navigation Controller,並將Transition選為"Flip Horizontal" 製造翻牌的動態效果。

一切就緒後,便可以開始寫程式惹!

首先在mainViewController(字母按鈕列表頁)中 ,寫一個用來傳值的prepare() 。把按鈕上的文字傳到EnglishViewController(英文頁面)作為navigation bar上面的title。

override func prepare(for segue: UIStoryboardSegue, sender: Any?){ 
let but = sender as! UIButton
let controller = segue.destination as!
EnglishViewController
controller.alphabet = but.currentTitle!
}

EnglishViewController(英文頁面)中,先宣告alphabet 、lineArray 、array、vocabularIndex四個變數。其中vocabularIndex是用來索引陣列中的資料。

var alphabet:String = "" //navigation bar title上顯示的字
var lineArray = [""]
var array = [""]
var vocabularIndex = 0 //第幾筆資料

將單字跟句子的兩個Label拉IBOutlet ,再將"前一筆資料"跟"後一筆資料"的按鈕拉IBAction。

@IBOutlet weak var word: UILabel! //英文單字
@IBOutlet weak var sentenceLabel: UILabel! //英文句子
@IBAction func prevBtn(_ sender: Any) {} //前一筆資料的按鈕
@IBAction func nextBtn(_ sender: Any) {} //後一筆資料的按鈕

在viewDidLoad()中,寫入

self.navigationItem.title = alphabet

let path = Bundle.main.path(forResource: alphabet, ofType: "txt")

let content = try! String(contentsOfFile: path!, encoding:String.Encoding.utf16) //接收路徑跟編碼

array = content.components(separatedBy: "\n")//依斷行切割資料

show()

(1)self.navigationItem.title = alphabet 是讓navigation bar的title顯示為前一頁(mainViewController)傳來的按鈕上的英文字

(2)let path = Bundle.main.path(forResource: alphabet, ofType: “txt”),設定檔案的路徑,由前一頁傳來的alphabet值來決定呼叫哪個txt檔

(3)let content = try! String(contentsOfFile: path!, encoding:String.Encoding.utf16),取得檔案裡的資料

(4)array = content.components(separatedBy: “\n”) ,將txt中的資料用斷行來分隔,並將分隔後的每一行資料放入array陣列中 。由於txt檔中的資料長成下面這樣 :

每行由 英文單詞(空格)中文單詞(空格)英文句子(空格)中文句子 組成,所以用斷行的方式將資料區隔開後,array的長相就會變成:[ 英文單詞(空格)中文單詞(空格)英文句子(空格)中文句子, 英文單詞(空格)中文單詞(空格)英文句子(空格)中文句子, 英文單詞(空格)中文單詞(空格)英文句子(空格)中文句子]

之後再執行show()這個方法

func show(){
let line = array[vocabularIndex]
lineArray = line.components(separatedBy: "\t")//依空白切割資料
let vocabulary = lineArray[0]
let sentence = lineArray[2]
word.text = vocabulary
sentenceLabel.text = sentence
}

(1)一開始宣告var vocabularIndex = 0初始值為0 ,所以let line = array[0],可以取出array陣列中的第一筆資料[英文單詞(空格)中文單詞(空格)英文句子(空格)中文句子],也就是txt檔中的第一行資料 。

(2)接著 lineArray = line.components(separatedBy: “\t”),用空格為依據來分隔資料。剛剛使用let line = array[0]取出了[英文單詞(空格)中文單詞(空格)英文句子(空格)中文句子]這筆資料後,用空格進行分隔後存入lineArray陣列後,就會變成[英文單詞,中文單詞,英文句子,中文句子]。

(3)let vocabulary = lineArray[0] =英文單詞
 let sentence = lineArray[2]=英文句子

(4)將vocabulary跟 sentence的值指派給word跟sentenceLabel這兩個label做顯示

然後回頭來處理prevBtn跟nextBtn這兩個按鈕的IBAction

@IBAction func prevBtn(_ sender: Any) {
vocabularIndex -= 1
if vocabularIndex < 0 {
vocabularIndex = array.count-1
//如果已經在第一行了,就秀最後一行
}
show()
}

@IBAction func nextBtn(_ sender: Any) {
vocabularIndex += 1
if vocabularIndex > array.count-1 {
vocabularIndex = 0
//如果已經在第一行了,就秀第一行
}
show()
}

按"前一筆資料"按鈕時,陣列索引值-1(vocabularIndex -= 1),讀取前一筆資料。按"後一筆資料"按鈕時,陣列索引值+1(vocabularIndex+= 1),讀取後一筆資料。

如果目前畫面中讀取的是第一行資料array[0],按下"前一筆資料"的按鈕,就秀出txt檔中的最後一筆資料。

如何得知txt檔中有幾行,可以使用array.count這個方法來得知陣列中的元素數。例如array[]中有100筆資料,array.count就會=100,那要讀出最後一筆資料的寫法就是array[99]。因此當array[0],0-1<0, 就執行vocabularIndex = array.count-1來讀取最後一筆資料。

換言之當畫面中已經秀出最後一筆資料時,按了後一筆資料的按鈕,就將vocabularIndex值歸0,秀出第一筆資料。

再使用prepare(),將資料傳到下一頁(ChineseViewController)。因為EnglishViewController跟ChineseViewController中間夾了一個Navigation Controller,所以需要轉手一下。然後再將linearray陣列[英文單詞,中文單詞,英文句子,中文句子]中的lineArray[1]=中文單詞跟lineArray[3]=中文句子,還有用於顯示navigation title的alphabet值傳到ChineseViewController。

override func prepare(for segue: UIStoryboardSegue, sender: Any?){

let navController = segue.destination as! UINavigationController
let chiController = navController.topViewController as! ChineseViewController

chiController.vocabulary = lineArray[1]
chiController.sentence = lineArray[3]
chiController.alphabet = alphabet

}

ChineseViewController中,先宣告vocabulary 、sentence、alphabet三個變數來接值。然後將顯示"中文單詞"跟"中文句子"的label拉IBOutlet連線。

再從navigation bar上的"英文"按鈕拉IBAction,使用" self.dismiss(animated: true, completion:nil)"的方法返回英文頁。

@IBAction func showEnglish(_ sender: Any) {
self.dismiss(animated: true, completion:nil)
}

viewDidLoad()中,處理一下接值與顯示,就終於告一段落惹!

word.text = vocabulary
sentenceLabel.text = sentence
self.navigationItem.title = alphabet

這個月,姊姊從加拿大帶小外甥回台探親 ,下了班就只想跟寶包玩 ,把swift丟一邊!! 小寶包真得好可愛,不能只有我看到 。

mainViewController
EnglishViewController
ChineseViewController