心理測驗-你把自己隱藏多深?

IBSegueAction 2 種寫法, popToRootViewController

--

成品:進度落後太多想說不管美觀可做很快,結果還是搞了挺久…

▲已和心理測驗不熟,挑很久才用這但它圖超醜就當練習功能啦🤷🏻‍♀️
▲發現自己問了彼得白癡問題還問錯… 學越多腦袋越當機😵
▲參考來源為此網站,有興趣的人可以測看看!

前置作業

▲找心理測驗與圖,配置 Storyboard,首頁於此完成無寫程式
▲新增檔案: 1 swift,2 ViewController (左側藍 / 黃部分)
▲將由 Library 新增之 ViewController 與其各自配合 (右側上紅框 Class)
▲跳頁需求因此最後一頁 Storyboard ID 需取名 (右側下紅框)
▲加 Navigation Controller,拉Segue
▲ 3 個綠色 button Tag 依序設定 1,2,3

🟣 QNR.swift

新增 Swift File struct定義 Question / Result 型別:options 用 Array

import Foundationstruct Question {
let question: String!
let options: [String]!
let image: String!
}
struct Result {
let type: String!
let image: String!
let analysis: String!
}

🟣 QuestionsViewController

拉 IBOutlet: 3 選項拉 Outlet Collection

@IBOutlet weak var questionLabel: UILabel!@IBOutlet weak var picImageView: UIImageView!@IBOutlet var optionsButton: [UIButton]!

宣告:題目此只列舉第 1 題寫法

var index = 0
var point = 0
var questions = [
Question(question: “女人為何掩面?她的情緒為何?”, options: [“悲傷,
發現丈夫的婚外情”, “憂慮,丈夫酒醉在床上”, “關心,丈夫病重可能即將死
去”], image: “01”),
....
]

定義 updateUI():依 index 更換 UI,用迴圈與標題設定顯示 button 字樣

func updateUI() {
questionLabel.text = questions[index].question
picImageView.image = UIImage(named: questions[index].image)
for i in 0…2 {
optionsButton[i].setTitle(questions[index].options[i], for:
.normal)
}

}

預設畫面:第一題 UI

override func viewDidLoad() {
super.viewDidLoad()
updateUI()
}

拉 IBAction

▲用button sender.tag 值來看分數加 1 / 2 / 3,依 index 變換而更動題目
▲每次有 Array 絕對 out of range 很多次才成功 🤦🏻‍♀️
▲Storyboard ID 取名為最後 1 題選擇完後可用 performSegue 自動跳畫面
▲或許有人最後不按「再玩一次」按 Back,此處加上恢復預設畫面設定

@IBAction func optionChosen(_ sender: UIButton) {
if index != 6 {
switch sender.tag {
case 1:
point += 1
case 2:
point += 2
default:
point += 3
}
index += 1
updateUI()
} else {
switch sender.tag {
case 1:
point += 1
case 2:
point += 2
default:
point += 3
}
performSegue(withIdentifier: “result”, sender: nil)
index = 0
updateUI()
point = 0

}
}

拉 IBSegueAction:從 segue 右鍵拉至 QuestionsViewController

▲拉完後會自動出現這個 ↓

@IBSegueAction func showResult(_ coder: NSCoder, sender: Any?,   segueIdentifier: String?) -> ResultViewController? {
return <#ResultViewController(coder: coder)#>
}

★去 ResultViewController 透過 property 儲存傳送的資料

var sum = 0

▲再回 QuestionsViewController 把這程式寫完
➞把這頁的 point 分數資料傳到下頁的 sum

@IBSegueAction func showResult(_ coder: NSCoder, sender: Any?,   segueIdentifier: String?) -> ResultViewController? {
let controller = ResultViewController(coder: coder)
controller?.sum = point
return controller
}

🟣 ResultViewController:基本 UI 變化和之前方法一樣便不提

分數判斷:因 sum 分數測出不同結果,而 UI 也依 index 改變

override func viewDidLoad() {
super.viewDidLoad()
switch sum {
case 7, 8, 9, 10, 11:
updateUI()
case 12, 13, 14, 15, 16:
index = 1
updateUI()
default:
index = 2
updateUI()
}
}

再玩一次

▲因有 Navigation 用 dismiss(animated: true, Completion: nil) 會失敗
▲友人教我用 popToRootViewController 回首頁

@IBAction func playAgain(_ sender: UIButton) {
self.navigationController?.popToRootViewController(animated:true)
}

完整程式碼 (第 1 種,較好第 2 種寫法請繼續往下看 )

QNR.swit,QuestionsViewController,ResultViewController

✅✅✅ 較好寫法:定義 init,由參數設定 property:只列須改之處

🟣 QuestionsViewController

將原先 stored property 改掉

var point = 0   改成  var point: Int!

ViewDidLoad 加上 point = 0:本來沒有這行

override func viewDidLoad() {
super.viewDidLoad()
point = 0updateUI()
}

🟣 ResultViewController

⭐️ 定義 init,由參數設定 property

▲使用常數並將原本的 var sum = 0刪除
➞其實可一樣設 point 代表同個值,這只是為了區分才另取 sum
▲包含型別 NSCoder 的參數,並在 init 裡呼叫 super.init(coder: coder)
➞因 controller 是在 storyboard 設計,controller 畫面存在 coder 裡
➞初始便必須經過 init(coder:)
▲寫完出現紅色修正標示屬正常,請直接按 fix

let sum: Intrequired init?(coder: NSCoder, sum: Int) {
self.sum = sum
super.init(coder: coder)

}

required initializer:防止父類別的 initializer 失傳

▲修正後會自動出現以下要讓程式閃退的 function
▲但此 APP 流程永遠不會呼叫這 function,所以可以放心
▲相關解說請參考彼得教學

required init?(coder: NSCoder) {fatalError(“init(coder:) has not been implemented”)}

🟣 再回到 QuestionsViewController

建立要傳的資料,因只有 1 行便可省略 return 不寫

@IBSegueAction func showResult(_ coder: NSCoder) -> ResultViewController? {     ResultViewController(coder: coder, sum: point)}

完整程式碼:第 2 種較好寫法

QNR.swit,QuestionsViewController,ResultViewController

--

--