#21 製作 MBTI 十六型人格測試 App
Data transfer/ 用 Delegate 初始前一頁資訊
邁爾斯 — 布里格斯性格分類指標(英語:Myers-Briggs Type Indicator,簡稱 MBTI),為性格分類理論模型的一種,其基本理論是根據瑞士心理分析家卡爾.榮格於 1921 年所出版的書籍《心理類型》。榮格認為人的認知有四個部份,各有兩個極端。MBTI 測驗就是依此理論為基礎所發展出來的!
Model
Questions.swift 檔
每個問題(Question)有選項陣列(choices),每個選項(Choice)有內容(content)和分數(score)。
questions(Question 的物件陣列)。
Personalities.swift 檔
每個性格(Personality)有名稱(name)、取向(category)、型態(type)、描述(description)。取向是 enum,有四種。
personalities(Personality 的物件陣列)。
View
Class 名稱要寫上。ResultViewController 的 Storyboard ID 也不要忘了。
UI 小技巧:把 ResultViewController 最底層 view 設為 clear color,第二層 view 設為透明度 30% 的黑色。
Controller
ViewController
IBOutlet
進度條、兩個按鈕。
viewDidLoad 內
呼叫畫漸層背景函式;讓按鈕變圓角。
畫漸層背景函式:
func createGradientBackground() {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = view.bounds
gradientLayer.colors = [
UIColor(red: 50/255, green: 8/255, blue: 103/255, alpha: 1).cgColor,
UIColor(red: 46/255, green: 206/255, blue: 207/255, alpha: 1).cgColor,
]
gradientLayer.startPoint = CGPoint(x: 0.5, y: 0)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
gradientLayer.locations = [0, 0.6]
view.layer.insertSublayer(gradientLayer, at: 0)
}
displayQuestion 函式:更新每一題的按鈕文字
var currentQuestionIndex = 0
displayQuestion() //viewDidLoad內要呼叫
兩個按鈕連到一個 IBAction
按鈕按下去後,把目前題目的指標+1,然後用這個指標更新進度條。
再來用「指標等於或小於問題數」判斷是否還有下一題,分成兩狀況。
沒下題了(
currentQuestionIndex == questions.count
)
・加總分數總分、得出人格型態
用 computePersonalityType 函式得知是 INTJ / INTP / ENTJ … 共 16 種人格型態的哪一種,回傳到一個區域變數 personalityTypeText。該函式單純將每個 Question 的物件所帶的 score 加來加去和比大小,因為很冗就不貼出來了。
計算方式是根據 Google 到的文件:https://csc.nutc.edu.tw/ezfiles/34/1034/img/1292/175552181.pdf。
接著把 personalityTypeText 丟進 switch 做比較,得到該型態屬於 personalities 陣列的第幾個 Personality 的物件。用區域變數 index 來代表這邊的「第幾個」。
// 區域變數
var personalityTypeText = ""
var index = 0
・轉場與傳資料
還有下題(currentQuestionIndex < questions.count
)
透過 sender 的 tag 為 0 或 1,區分按了哪個按鈕。
點到上面或下面的按鈕,對應物件內的 score 要加 1。如此就可以紀錄每個從每個選項得到 0 分還是 1 分。(沒被選到過/有被選到過)
注意 currentQuestionIndex
此時代表下一題的 index,所以要減一才能正確取到本題物件。
最後呼叫 displayQuestion 函式顯示下題。
ResultViewController
IBOutlet
對話窗 view、image view、名稱標籤、型態標籤、描述標籤。
viewDidLoad / viewWillAppear
「每次」進入畫面時 viewDidAppear 就會被呼叫,而 viewDidLoad 只會在 App 加載時被呼叫一次。
每個作答回合,送給 ResultViewController 的資料都不同,因此必須把「用帶有前一頁資料的屬性更新元件」的程式寫在 viewWillAppear 裡面。
背景圖顏色要對應四種取向,可以用 enum 搭配 switch 完成。
實現 Restart 功能的步驟
- 發明一個 ResultViewControllerProtocol 協定,函式命名為 dialogDismissed:
2. ResultViewController 內宣告 delegate property:
var delegate: ResultViewControllerProtocol?
3. ViewController 遵從 ResultViewControllerProtocol。
4. 將 ResultViewController 的 delegate 設為 ViewController:
5. 定義 dialogDismissed 函式:
將 Question 的物件內的 score 歸零、指標回到第1題、進度條歸零,最後再重新顯示問題。
6. 呼叫 dialogDismissed 函式:
寫在 ResultViewController 的按鈕觸發函式內。
先用 dismiss 把 presented modally 的 view controller(在此為 ResultViewController)關掉。
接著 delegate 呼叫 dialogDismissed,就能回到最初的起點。