#21 製作 MBTI 十六型人格測試 App

Data transfer/ 用 Delegate 初始前一頁資訊

--

Demo

邁爾斯 — 布里格斯性格分類指標(英語: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 函式顯示下題。

在 Storyboard 設定兩個按鈕的 tag,分別是 0 和 1

ResultViewController

IBOutlet

對話窗 view、image view、名稱標籤、型態標籤、描述標籤。

viewDidLoad / viewWillAppear

「每次」進入畫面時 viewDidAppear 就會被呼叫,而 viewDidLoad 只會在 App 加載時被呼叫一次。

每個作答回合,送給 ResultViewController 的資料都不同,因此必須把「用帶有前一頁資料的屬性更新元件」的程式寫在 viewWillAppear 裡面。

背景圖顏色要對應四種取向,可以用 enum 搭配 switch 完成。

實現 Restart 功能的步驟

  1. 發明一個 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,就能回到最初的起點。

--

--