Quizzler (4)
이어서… quizBrain.swift에서 function checkAnswer를 Bool type으로 하고 정답일때 true/ 틀렸을때 false return하게 하였다.
1
2
3
4
5
6
7
func checkAnswer(_ userAnswer: String) -> Bool {
if userAnswer == quiz[questionNumber].answer {
return true
} else {
return false
}
}
그리고 다시 viewController로 돌아가서 위와 같이 수정하였다.
이걸 다르게 또 보는사람이 쉽게 하기위해 표현이 가능할까?
이렇게 직관적으로 보이게도 할 수 있다.
Challenge! 그렇다면. 현재 아래 code는 quizBrain.swift에 관련 코드를 넣지 않고 입력한 상태이다.
아래코드가 작동하게 하려면 quizBrain에 어떤 code를 작성해야할지 한번 try해보자! before
1
2
3
4
5
@objc func updateUI() {
questionLabel.text = quiz[questionNumber].text
trueButton.backgroundColor = UIColor.clear
falseButton.backgroundColor = UIColor.clear
progresBar.progress = Float(questionNumber + 1 ) / Float(quiz.count)
after
1
2
3
4
5
6
@objc func updateUI() {
questionLabel.text = quizBrain.getQuestionText()
trueButton.backgroundColor = UIColor.clear
falseButton.backgroundColor = UIColor.clear
progresBar.progress = quizBrain.getProgress()
}
quizBrain.swift 내가한것
1
2
3
4
5
6
7
8
9
10
11
12
func getQuestionText () -> String {
var quiz : String = quiz[questionNumber].text
return quiz
}
func getProgress() -> Float {
var progress : Float = Float(questionNumber + 1) / Float(quiz.count)
return progress
}
강의에서의 코드
1
2
3
4
5
6
7
8
9
10
func getQuestionText () -> String {
return quiz[questionNumber].text
}
func getProgress() -> Float {
let progress = Float(questionNumber + 1) / Float(quiz.count)
return progress
}
뭐 또이또이하다 다만 차이라면 progress를 나는 var로 하였고 강의에서는 let으로 하였다.
그리고 questionNumber를 1씩 증가해주던 부분을 함수화 하여 quizBrain에 넣어주었다
1
2
3
4
5
6
7
func nextQuestion() {
if questionNumber + 1 < quiz.count {
questionNumber += 1
} else {
questionNumber = 0
}
}
그랬더니 immutable즉 변할 수 없는 값이라고 에러가 뜬다.
어떻게 해야할까?
여기서 immutable이란??
- 불변성을 이야기한다.
우선 Struct = Blueprint 라고 볼 수 있다. 즉, 우리가 어떤 코드를 짤때에 있어 청사진을 그리는것이라고 이해하면 될 것 같다.
그리고 그 청사진을 그린것을 실체화하는걸 initializing이라고 보면 되겠다.
Blueprint -> actualization
var -> variable / mutable let -> immutable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
struct Town {
let name : String
var citizens : [String]
var resources : [String : Int]
init (name : String, citizens : [String], resources : [String : Int]){
self.name = name
self.citizens = citizens
self.resources = resources
}
func fortify() {
print("Defences increased!")
}
//func harvestRice()
}
var anotherTown = Town(name: "Nameless Island", citizens: ["Tom Hanks"], resources: ["Coconuts" : 100])
var myTown = Town(name: "Harold Island", citizens: ["Harold", "Timothy"], resources: ["Wool" : 75])
myTown.citizens.append("Keanu Reeves")
anotherTown.citizens.append("Wilson")
print(anotherTown.citizens)
이렇게 되어있는 코드에 sturcture 내부에 값을 한번 넣어보자!
1
2
3
4
func harvestRice() {
resources["Rice"] = 100
}
structure 내부에 function을 만들어, resources에 Rice라는 항목을 만들고 100이라는 값을 넣었다. 즉 [“Rice” : 100] 의 형태로 넣었다. 하지만 아래와 같이 에러가 발생한다.
우리가 위에 정의한 self는 기본적으로 immutable 즉, 변할 수 없는 값이기 때문이다.
- let 과 함께 정의된다고 생각하면 된다.
Q: Self가 없는데 어디있는건가? A: 우리가 적은
1
resources["Rice"] = 100
이것은 사실
1
self.resources["Rice"] = 100
의 줄임 표현이다.
Q: 그렇다면 structure에서는 값을 변경할 수 없나? A: 아니다 아래와 같이 func 앞에 mutating을 추가해주면 된다.
1
2
3
4
mutating func harvestRice() {
--------
resources["Rice"] = 100
}
그럼 함수를 호출하고 출력을 해보자. 이렇게 추가된걸 볼 수 있다.
myTown.harvestRice()함수를 호출하지않으면, 아래와 같다.
함수 앞에 mutating을 붙이면 self는 var와 같은 역할을 수행하게 되고, 우리는 우리의 struct안에서 값을 자유롭게 바꿀 수 있다.
즉 struct는
- 값이 변할 수 없는 struct
- 값이 변하는 struct
이렇게 두개로 나눌 수 있다.
Q: 우리가 현재 myTown을 let아닌 var로 정의 했는데, let를 사용하면 harvestRice 함수를 호출을 할수 있을까?
1
2
3
var myTown = Town(name: "Harold Island", citizens: ["Harold", "Timothy"], resources: ["Wool" : 75])
// --- var를 let으로
let myTown = Town(name: "Harold Island", citizens: ["Harold", "Timothy"], resources: ["Wool" : 75])
A: Nope! 왜냐면 let은 바꿀수없는 상수이므로, 값을 변화시켜주는 harvestRice 함수를 호출 할 수없다. 그리고 let을 사용해서 매개변수를 정의를 하면, structure내의 모든 Properties들은 immutable이 되고, 또한 harvestRice 함수 앞에 적어둔 mutating또한 작동을 하지 않는다!!!
다시 내용으로 들어와서… immutable즉 변할 수 없는 값이라고 에러가 뜬다. 이부분에 대해 다시 이야기를 해보자. structure내부에서 questionNumber가 1씩 증가를 하거나 0으로 돌린다는건데 immutable이라 바꾸질 못한다. 그래서 func 앞에 mutating을 적어주었다.
1
2
3
4
5
6
7
mutating func nextQuestion() {
if questionNumber + 1 < quiz.count {
questionNumber += 1
} else {
questionNumber = 0
}
}
잘 작동한다.
challenge!
정답을 맞추면 score가 올라가게 해보자!
Let’s think!
- 로직은 어떻게 짜여야 할까?
- 우선 생각해본 Logic flow는 정답일때 score가1씩 증가, 오답일때는 값이 그대로, 그리고 마지막문제에서 첫번째 문제로 돌아갈때 score 를 0으로 한다.
- 먼저 무엇을 해야할까?
- QuizBrain.swift에 함수를 정의한다.
- func getScore ~
- 함수를 정의를 했다. 그다음에는 어떻게 해야할까?
- 우선 var score = 0 이라는 매개변수를 하나 만들어 주었다.
- 그 변수를 어디에 쓸건지?
- 우선 로직 플로우 그대로 ```swift mutating func checkAnswer(_ userAnswer: String) -> Bool { if userAnswer == quiz[questionNumber].answer { score += 1 // updated! return true } else { return false } }
mutating func nextQuestion() { if questionNumber + 1 < quiz.count { questionNumber += 1 } else { questionNumber = 0 score = 0 // updated! } } ``` 처음에 내가 생각한게 맞나싶어서 했고 테스트만 안하고 확신이 없어서 완성한 코드를 더 꼬아버렸다. 그러다 도저히 안되어서 강의를 봤는데 내가생각하고 작성한게 맞았다. 확신을 좀 가지자…