Peter’s 100 task #4–1 誰是臥底

新增自訂暱稱與忘詞功能,使用Google Spreadsheet當後台

Tommy
彼得潘的 Swift iOS / Flutter App 開發教室
9 min readDec 19, 2020

--

前篇連結

新增功能說明

自訂暱稱功能

點擊自訂暱稱按鈕後跳出Alert,內容為依據玩家人數產生textField,輸入完畢按下OK按鈕,存取輸入的名字

利用.addTextField(configurationHandler:),將textField加入alert

於configurationHandler參數closure內設定textField之屬性

忘詞功能

點擊忘詞按鈕出現忘詞頁面,利用IBSegueAction做資料傳遞,忘詞頁面內容為依據玩家人數產生Button,點擊玩家Button後顯示該玩家的題目

新增一個自訂ViewController類別,名稱為ForgetQuestionViewController

func initButton() {
// 初始玩家暱稱
for i in 0...playerNumber-1 {
playerForgetQuestionButton[i].setTitle(player[i].name, for: .normal)
}
// 初始按鈕數量
var index = playerForgetQuestionButton.count
print(index)
while index > player.count {
print(player.count)
//playerVoteButton[index-1].isHidden = true
playerForgetQuestionButton[index-1].alpha = 0
index -= 1
}
}

於自訂類別內建立一個initButton()依據玩家人數顯示對應Button數量,在viewDidLoad()呼叫initButton()

@IBAction func showQuestion(_ sender: UIButton) {
switch sender {
case playerForgetQuestionButton[0]:
confirmQuestion(index: 0)
case playerForgetQuestionButton[1]:
confirmQuestion(index: 1)
case playerForgetQuestionButton[2]:
confirmQuestion(index: 2)
case playerForgetQuestionButton[3]:
confirmQuestion(index: 3)
case playerForgetQuestionButton[4]:
confirmQuestion(index: 4)
case playerForgetQuestionButton[5]:
confirmQuestion(index: 5)
case playerForgetQuestionButton[6]:
confirmQuestion(index: 6)
case playerForgetQuestionButton[7]:
confirmQuestion(index: 7)
case playerForgetQuestionButton[8]:
confirmQuestion(index: 8)
case playerForgetQuestionButton[9]:
confirmQuestion(index: 9)
default:
break
}
}

將每個Button都拉進IBAction,利用Switch判斷按下哪個按鈕,並呼叫顯示題目的func

判斷目前Button的Titile,若為玩家名稱則顯示題目,反之則顯示玩家名稱

利用 Google Spreadsheet 當後台,作為題目資料來源

建立Google sheets表單

產生JSON

題目資料陣列放在feed->entry,其中gsx$civilianquestion及gsx$spyquestion為儲存題目內容的欄位,由於gsx$及$t無法做為物件屬性名稱,因此需利用enum CodingKeys將其轉換為可使用的名稱

struct SearchResponse: Codable {
let feed: QuestionData

struct QuestionData: Codable {
let entry: [IdentityQuestion]
}
}
struct IdentityQuestion: Codable {
let civilianQuestion: Question
let spyQuestion: Question

enum CodingKeys: String, CodingKey {
case civilianQuestion = "gsx$civilianquestion"
case spyQuestion = "gsx$spyquestion"
}
}
struct Question: Codable {
let question: String

enum CodingKeys: String, CodingKey {
case question = "$t"
}
}

自訂的資料型別遵從Codable(可編碼、解碼)或DeCodable(可解碼)

將JSON內的物件的Key設定為自訂的資料型別的屬性名稱(需與Key一模一樣)

在自訂型別內加入enum CodingKeys,並設定raw value加以描述屬性名稱對應JSON Key(注意:每個屬性名稱都要有對應之case,無需加以描述則不用設定raw value)

這樣就可以順利解析啦~

將抓題庫程式寫成func,抓題庫時以ActivityIndicatorView顯示loading中

宣告全域變數question存取題目

var question = [IdentityQuestion]()

利用UIActivityIndicatorView表示下載中,以及isUserInteractionEnabled屬性讓畫面無法操作

loadingActivityIndicator = UIActivityIndicatorView(style: .medium)
loadingActivityIndicator.center = view.center
view.addSubview(loadingActivityIndicator)

建立loadingActivityIndicator變數為UIActivityIndicatorView物件,設定對齊畫面中央,並將ActivityIndicatorView加入view

實現將資料下載好後放至question陣列內

利用completionHandler func當參數,設定完成後執行的動作,func內需放入型別為[IdentityQuestion]

loadingActivityIndicator.startAnimating()
view.isUserInteractionEnabled = false

進入fetchQuestion func時,呼叫.startAnimating啟動loadingActivityIndicator,並將isUserInteractioinEnabled屬性設為false,讓使用者無法操作畫面

在viewDidLoad()呼叫fetchQuestion func,並在completionHandler closure內將資料存取

DispatchQueue.main.async {
self.loadingActivityIndicator.stopAnimating()
self.view.isUserInteractionEnabled = true
}

完成下載後將loadingActivityIndicator關閉(關閉後預設為隱藏該元件),並且將isUserInteractionEnabled設為true,讓使用者可以操作畫面

大致上想實現的功能都完成啦~原本只是想把自訂暱稱與忘詞功能寫完,後來突然看到peter說可以用google spreadsheets做資料來源,也順利實現從網路上抓題庫的想法。

後續如果有發現什麼問題會再陸續更新,有興趣的人可以去github載來玩玩看喔,有做autolayout應該是目前的iphone都可以玩~

--

--