목표 : MVC 패턴에 대해 알아본다.
Quizzler Project
main storyboard elements를 viewController
로 연결해준다.
class ViewController: UIViewController {
@IBOutlet weak var questionLabel: UILabel!
@IBOutlet weak var progressBar: UIProgressView!
@IBOutlet weak var trueBtn: UIButton!
@IBOutlet weak var falseBtn: UIButton!
override func viewDidLoad()
viewDidLoad
는 앱을 실행할 때 딱 한 번만 실행되는 view
이다. 만약 앱을 실행하자마자 퀴즈의 텍스를 보여주려면 다음과 같이 퀴즈 배열을 작성하고 이 코드 안에 다음과 같이 작성하면 된다.
let quiz = [
"달걀은 어린 닭이 낳은 것일수록 그 크기가 크다",
"달걀은 뾰족한 쪽에 호흡하는 공간이 있어서 둥근 쪽을 아래로 해서 보관해야 합니다",
"꺼벙이란 꿩의 새끼를 말합니다",
"외출 전에 자외선 차단제를 바르면 햇볕을 오래 받아도 무방하다"
]
//viewDidLoad는 앱이 실행될때 단 한번만 실행됨.
override func viewDidLoad() {
super.viewDidLoad()
//questionLabel.text = quiz.randomElement()
questionLabel.text = quiz[0]
}
@IBAction func PressedAnswerBtn(_ sender: UIButton) {
// some code
}
}
UpdateUI
버튼을 눌렀을 때 질문이 바뀌게 하는 방법
1. numberOfQuestion
변수 생성
2. questionLabel text
의 배열을 numberOfQuestion
으로 수정
3. PressedAnswerBtn
에 numberOfQuestion + 1
추가
문제점 viewDidLoad
는 앱이 실행될 때 단 한 번만 업데이트하기 때문에 questionLabel
이 Button
이 press 되었을
때도 업데이트돼야 한다.
해결방법 UpdateUI
함수를 만들어 호출
class ViewController: UIViewController {
...
let quiz = [
..
]
var numberOfQuestion = 0
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
}
@IBAction func PressedAnswerBtn(_ sender: UIButton) {
numberOfQuestion += 1
updateUI()
}
func updateUI() {
questionLabel.text = quiz[numberOfQuestion]
}
}
1D / 2D Array
1D Array 검색
2D Array 검색
연습
만약 2D Array
에서 다음과 같은 배열이 있을 때 숫자 9를 프린트하려면 다음과 같다.
let twoDArray = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
print(twoDArray[2][2]) //9
Quiz 배열 수정
let quiz = [
["달걀은 어린 닭이 낳은 것일수록 그 크기가 크다", "False"],
["달걀은 뾰족한 쪽에 호흡하는 공간이 있어서 둥근 쪽을 아래로 해서 보관해야 합니다", "False"],
["꺼벙이란 꿩의 새끼를 말합니다", "Ture"],
["외출 전에 자외선 차단제를 바르면 햇볕을 오래 받아도 무방하다", "Fasle"]
]
...
func updateUI() {
questionLabel.text = quiz[numberOfQuestion][0] // 2D Array
}
}
Quiz 정답 버튼 구현
정확한 정답을 눌렀을 때를 구별하기 위한 코드를 구현해야 한다.
1. userAnswer
상수 생성 > sender.currentTitle
2. currentAnswer
상수 생성 > quiz의 numberOfQuestion
배열의 [1]
(true or false) 할당
3. if문을 사용하여 정답 혹은 오답 프린트
4. numberOfQuestion
이 quiz.count
보다 작으면 +1을 더해줌
문제점 여전히 quiz의 질문이 끝나면 앱이 크래쉬 됨.
해결방법 만약 numberOfQuestion
가 4이면 quiz.count
가 4이기 때문에 다음 버튼을 눌렀을 때 앱이 크래쉬 난다. 그렇기 때문에 처음부터 numberOfQuestion
에 +1
을 하고 조건문을 작성하면 해결된다.
5. else문에 numberOfQuestion
을 0으로 정해주어 퀴즈가 끝나도 계속 반복될 수 있도록 해준다.
@IBAction func PressedAnswerBtn(_ sender: UIButton) {
let userAnswer = sender.currentTitle
//numberOfQuestion의 [1]이 정답(true or false)이 위치해있기 때문
let currentAnswer = quiz[numberOfQuestion][1]
// 정답 확인
if userAnswer == currentAnswer {
print("정답입니다!")
} else {
print("오답입니다! 정답은 \(quiz[numberOfQuestion][1])")
}
// 정답 개수 확인
if numberOfQuestion + 1 < quiz.count {
numberOfQuestion += 1
} else {
numberOfQuestion = 0
}
updateUI()
}
Quiz list - Struct
지저분한 quiz list
를 새로운 sturct
파일로 만들어서 코드를 구현할 수 있다. struct에 대한 문법
// Questions.swift
import Foundation
import UIKit
struct Questions {
var questionText: String
var answer: String
init(questionText: String, answer: String) {
self.questionText = questionText
self.answer = answer
}
}
1. viewController
에서 Question struct
호출
2. currentAnswer
정답 코드 수정
3. UpdateUI
함수 수정
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var questionLabel: UILabel!
@IBOutlet weak var progressBar: UIProgressView!
@IBOutlet weak var trueBtn: UIButton!
@IBOutlet weak var falseBtn: UIButton!
let quiz = [
Questions(questionText: "달걀은 어린 닭이 낳은 것일수록 그 크기가 크다", answer: "False"),
Questions(questionText: "달걀은 뾰족한 쪽에 호흡하는 공간이 있어서 둥근 쪽을 아래로 해서 보관해야 합니다", answer: "False"),
Questions(questionText: "꺼벙이란 꿩의 새끼를 말합니다", answer: "Ture"),
Questions(questionText: "외출 전에 자외선 차단제를 바르면 햇볕을 오래 받아도 무방하다", answer: "False"),
]
var numberOfQuestion = 0
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
}
@IBAction func PressedAnswerBtn(_ sender: UIButton) {
let userAnswer = sender.currentTitle
//numberOfQuestion의 정답이 있는 .answer로 수정
let currentAnswer = quiz[numberOfQuestion].answer
// if문
if userAnswer == currentAnswer {
print("정답입니다!")
} else {
print("오답입니다! 정답은 \(quiz[numberOfQuestion].answer)")
}
if numberOfQuestion + 1 < quiz.count {
numberOfQuestion += 1
} else {
numberOfQuestion = 0
}
updateUI()
}
func updateUI() {
questionLabel.text = quiz[numberOfQuestion].questionText
}
}
let quiz = [
Questions(questionText: "달걀은 어린 닭이 낳은 것일수록 그 크기가 크다.", answer: "False"),
Questions(questionText: "달걀은 뾰족한 쪽에 호흡하는 공간이 있어서 둥근 쪽을 아래로 해서 보관해야 하는가?", answer: "False"),
Questions(questionText: "원숭이에게도 지문이 있다?", answer: "Ture"),
Questions(questionText: "외출 전에 자외선 차단제를 바르면 햇볕을 오래 받아도 무방한가?", answer: "False"),
Questions(questionText: "1970년대도 포도, 사과 다이어트 같은 원푸드 다이어트는 폭발적인 인기를 끌었는가?", answer: "True"),
Questions(questionText: "승리의 V는 남북전쟁에서 승리한 후 에이브러험 링컨이 처음 사용하였는가?", answer: "False"),
Questions(questionText: "뽀뽀뽀 노래 중에 뽀 가 총 24번 나온다?", answer: "True"),
Questions(questionText: "국가대표 축구선수 안정환의 포지션은 센터백인가?", answer: "False"),
Questions(questionText: "딸기는 장미과에 속하는가?", answer: "True"),
Questions(questionText: "우리나라에 가장 넓은 차선은 광화문 앞에 16차선 인가?", answer: "True"),
Questions(questionText: "물고기도 기침을 하는가?", answer: "True"),
Questions(questionText: "오이는 과일이 아니라 채소인가", answer: "True")
]
ProgressView / UIColor
정답 또는 오답을 선택했을 때 Print
를 하는 것이 아닌 버튼 배경색을 변경하고 지연 효과를 주어 오답인지 정답인지를 직관적으로 볼 수 있게 할 수 있다. 또 ProgressView
를 사용해보려고 한다.
1. if문에 sender.background = UIColor
를 사용한다.
2. view
가 Update 할 때마다 배경색을 되돌리기 위해 UIColor.clear
를 사용한다.
3. @IBAction
코드 내에 UpdateUI
에 지연 효과를 주어 잠깐 동안 정답 배경색을 나타나게 한다.
4. progressBar
를 보여주기 위해 UpdateUI
함수에 코드를 넣어준다.
5. Button
의 cornerRadius
를 viewDidLoad
안에서 수정해준다.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var questionLabel: UILabel!
@IBOutlet weak var progressBar: UIProgressView!
@IBOutlet weak var trueBtn: UIButton!
@IBOutlet weak var falseBtn: UIButton!
let quiz = [
Questions(questionText: "달걀은 어린 닭이 낳은 것일수록 그 크기가 크다.", answer: "False"),
Questions(questionText: "달걀은 뾰족한 쪽에 호흡하는 공간이 있어서 둥근 쪽을 아래로 해서 보관해야 하는가?", answer: "False"),
Questions(questionText: "원숭이에게도 지문이 있다?", answer: "Ture"),
Questions(questionText: "외출 전에 자외선 차단제를 바르면 햇볕을 오래 받아도 무방한가?", answer: "False"),
Questions(questionText: "1970년대도 포도, 사과 다이어트 같은 원푸드 다이어트는 폭발적인 인기를 끌었는가?", answer: "True"),
Questions(questionText: "승리의 V는 남북전쟁에서 승리한 후 에이브러험 링컨이 처음 사용하였는가?", answer: "False"),
Questions(questionText: "뽀뽀뽀 노래 중에 뽀 가 총 24번 나온다?", answer: "True"),
Questions(questionText: "국가대표 축구선수 안정환의 포지션은 센터백인가?", answer: "False"),
Questions(questionText: "딸기는 장미과에 속하는가?", answer: "True"),
Questions(questionText: "우리나라에 가장 넓은 차선은 광화문 앞에 16차선 인가?", answer: "True"),
Questions(questionText: "물고기도 기침을 하는가?", answer: "True"),
Questions(questionText: "오이는 과일이 아니라 채소인가", answer: "True")
]
var numberOfQuestion = 0
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
trueBtn.layer.cornerRadius = 20
falseBtn.layer.cornerRadius = 20
}
@IBAction func PressedAnswerBtn(_ sender: UIButton) {
let userAnswer = sender.currentTitle
//numberOfQuestion의 정답이 있는 .answer로 수정
let currentAnswer = quiz[numberOfQuestion].answer
// if문
if userAnswer == currentAnswer {
sender.backgroundColor = UIColor.green
} else {
sender.backgroundColor = UIColor.red
}
if numberOfQuestion + 1 < quiz.count {
numberOfQuestion += 1
} else {
numberOfQuestion = 0
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
UIView.animate(withDuration: 0.2) {
self.updateUI()
}
}
}
func updateUI() {
questionLabel.text = quiz[numberOfQuestion].questionText
trueBtn.backgroundColor = UIColor.clear
falseBtn.backgroundColor = UIColor.clear
progressBar.progress = Float(numberOfQuestion + 1) / Float(quiz.count)
}
}
MVC 패턴으로 코드 정리
MVC패턴을 사용해서 코드를 재사용하기 쉽고 관리하기 쉽게 수정할 수 있다. MVC 패턴에 대한 문법
New Group from Selection
폴더명을 Model, View, Controller로 바꾼다. Input / output 문법
Model (QuizBrain.swift 생성)
QuizBrain Model
을 구조체로 만들고 viewController
에 있던 코드를 가져오고 몇 가지 메서드를 만들어줘야 한다. 또, UpdateUI
부분에 오류 부분도 수정해줘야 한다. 에러난 두 부분을 QuizBrain
에 메서드로 만들어서 해결해줄 수 있다.
func updateUI() {
questionLabel.text = quiz[numberOfQuestion].questionText //error
progressBar.progress = Float(numberOfQuestion + 1) / Float(quiz.count) //error
trueBtn.backgroundColor = UIColor.clear
falseBtn.backgroundColor = UIColor.clear
}
// QuizBrain.swift
import Foundation
import UIKit
struct QuizBrain {
let quiz = [
Questions(questionText: "달걀은 어린 닭이 낳은 것일수록 그 크기가 크다.", answer: "False"),
Questions(questionText: "달걀은 뾰족한 쪽에 호흡하는 공간이 있어서 둥근 쪽을 아래로 해서 보관해야 하는가?", answer: "False"),
Questions(questionText: "원숭이에게도 지문이 있다?", answer: "Ture"),
Questions(questionText: "외출 전에 자외선 차단제를 바르면 햇볕을 오래 받아도 무방한가?", answer: "False"),
Questions(questionText: "1970년대도 포도, 사과 다이어트 같은 원푸드 다이어트는 폭발적인 인기를 끌었는가?", answer: "True"),
Questions(questionText: "승리의 V는 남북전쟁에서 승리한 후 에이브러험 링컨이 처음 사용하였는가?", answer: "False"),
Questions(questionText: "뽀뽀뽀 노래 중에 뽀 가 총 24번 나온다?", answer: "True"),
Questions(questionText: "국가대표 축구선수 안정환의 포지션은 센터백인가?", answer: "False"),
Questions(questionText: "딸기는 장미과에 속하는가?", answer: "True"),
Questions(questionText: "우리나라에 가장 넓은 차선은 광화문 앞에 16차선 인가?", answer: "True"),
Questions(questionText: "물고기도 기침을 하는가?", answer: "True"),
Questions(questionText: "오이는 과일이 아니라 채소인가", answer: "True")
]
var numberOfQuestion = 0
func checkAnswer(_ userAnser: String) -> Bool {
if userAnser == quiz[numberOfQuestion].answer {
return true
} else {
return false
}
}
func UpdateQuestionText() -> String {
return quiz[numberOfQuestion].questionText
}
func updateProgressBar() -> Float {
let progress = Float(numberOfQuestion + 1) / Float(quiz.count)
return progress
}
}
//Questions.swift
import Foundation
import UIKit
struct Questions {
var questionText: String
var answers: [String]
var correctAnswer: String
init(questionText: String, answers: [String], correctAnswer: String) {
self.questionText = questionText
self.answers = answers
self.correctAnswer = correctAnswer
}
}
viewController 수정
viewController
의 코드를 위와 같이 수정하고 보면 Question
이 넘어가는 부분(if numberOfQuestion + 1 < quiz.count
)이 오류가 생긴 것을 확인할 수 있다.
// viewController.swift
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var questionLabel: UILabel!
@IBOutlet weak var progressBar: UIProgressView!
@IBOutlet weak var trueBtn: UIButton!
@IBOutlet weak var falseBtn: UIButton!
// quizBrain Model을 init해서 가져옴
var quizBrain = QuizBrain()
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
trueBtn.layer.cornerRadius = 20
falseBtn.layer.cornerRadius = 20
}
@IBAction func PressedAnswerBtn(_ sender: UIButton) {
let userAnswer = sender.currentTitle!
let trueOrFalse = quizBrain.checkAnswer(userAnswer)
if trueOrFalse {
sender.backgroundColor = UIColor.green
} else {
sender.backgroundColor = UIColor.red
}
// Error
if numberOfQuestion + 1 < quiz.count {
numberOfQuestion += 1
} else {
numberOfQuestion = 0
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
UIView.animate(withDuration: 0.2) {
self.updateUI()
}
}
}
func updateUI() {
questionLabel.text = quizBrain.UpdateQuestionText()
progressBar.progress = quizBrain.updateProgressBar()
trueBtn.backgroundColor = UIColor.clear
falseBtn.backgroundColor = UIColor.clear
}
}
mutating
위 viewcontroller
에서 오류가 나있는 if
문은 퀴즈의 개수가 numberOfQuestion+1
보다 클 때 +1
을 하게하는 조건문이었다. 그것도 Model
로 함수를 새로 만들어 옮겨 주겠음! mutating 문법
문제점 그럼 이러한 오류가 발생하는데, self
는 immutable
(변경 불가성) 이기 때문에 사용이 불가능하다고 한다.
해결방법 func
키워드 앞에 mutating
키워드 사용
이 updateProgressBar
메서드와 nextQuestion
메서드의 차이점을 보면
updateProgressBar - 아무것도 변경하지 않고 progress의 값만 변경
nextQuestion - QuizBrain의 속성을 변경
그렇기 때문에 nextQuestion
메서드를 Mutating
키워드를 사용하여 속성이 변경 가능하게 만들어 준 것이다.
완성 파일
객관식 퀴즈 형태로 변경
위에서는 O, X 퀴즈로 두 가지 중 하나만 고를 수 있었는데 객관식으로 변경하려면 코드를 조금 변경해야 한다.
1. 객관식 레이블 추가
2. @IBOutlet
연결
3. QuizBrain
객관식 문제 수정 및 getAnswerList
메서드 추가
4. viewController
updateUI
함수에 getAnswerList
를 let
으로 가져옴
5. UIButton
의 텍스트 업데이트는 .text
가 아닌 .setTitle(String, for: )
을 사용함
완성 코드
Controller
<hide/>
// controllView.swift
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var questionLabel: UILabel!
@IBOutlet weak var progressBar: UIProgressView!
@IBOutlet weak var scoreLabel: UILabel!
@IBOutlet weak var answer1: UIButton!
@IBOutlet weak var answer2: UIButton!
@IBOutlet weak var answer3: UIButton!
// quizBrain Model을 init해서 가져옴
var quizBrain = QuizBrain()
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
answer1.layer.cornerRadius = 20
answer2.layer.cornerRadius = 20
answer3.layer.cornerRadius = 20
}
@IBAction func PressedAnswerBtn(_ sender: UIButton) {
let userAnswer = sender.currentTitle!
let trueOrFalse = quizBrain.checkAnswer(userAnswer)
// let currentAnser = quiz[numberOfQuestion].answer
if trueOrFalse {
sender.backgroundColor = UIColor.green
} else {
sender.backgroundColor = UIColor.red
}
quizBrain.nextQuestion()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
UIView.animate(withDuration: 0.2) {
self.updateUI()
}
}
}
func updateUI() {
let choiceAnswer = quizBrain.getAnswerList()
answer1.setTitle(choiceAnswer[0], for: .normal)
answer2.setTitle(choiceAnswer[1], for: .normal)
answer3.setTitle(choiceAnswer[2], for: .normal)
answer1.backgroundColor = UIColor.clear
answer2.backgroundColor = UIColor.clear
answer3.backgroundColor = UIColor.clear
questionLabel.text = quizBrain.UpdateQuestionText()
progressBar.progress = quizBrain.updateProgressBar()
scoreLabel.text = "현재 점수 : \(quizBrain.getScore())"
}
}
Model
<hide/>
//Questions.swift
import Foundation
import UIKit
struct Questions {
var questionText: String
var answers: [String]
var correctAnswer: String
init(questionText: String, answers: [String], correctAnswer: String) {
self.questionText = questionText
self.answers = answers
self.correctAnswer = correctAnswer
}
}
<hide/>
//QuizBrain.swift
import Foundation
import UIKit
struct QuizBrain {
let quiz = [
Questions(questionText: "다음중에서 내장고에 얼음을 위쪽에 두는 이유는?", answers: ["전도", "대류", "복사"], correctAnswer: "대류"),
Questions(questionText: "다음중 현재 우리나라에서 지정된 생태계 보전지역은?", answers: ["지리산, 대암산, 오봉산", "지리산, 낙동강, 대암산", "속리산, 낙동강, 지리산"], correctAnswer: "지리산, 낙동강, 대암산"),
Questions(questionText: "다음중 세계 3대강풍이 아닌것은?", answers: ["블리자드", "허리케인", "태풍"], correctAnswer: "블리자드"),
Questions(questionText: "다음중 연탄가스에 중독을 일으키는 성분은?", answers: ["메탄가스", "이산화탄소", "탄산가스"], correctAnswer: "이산화탄소"),
Questions(questionText: "다음중 노이즈에 대한 설명중 맞는것은", answers: ["환경오염", "도시에서의 각종공해", "각종 공해 소리가 점차 해소되어가는 상태"], correctAnswer: "도시에서의 각종공해"),
Questions(questionText: "다음중 우리나라 환율제도는 어느것인가?", answers: ["바스켓제도", "관리 통화제도", "변동환율제도"], correctAnswer: "변동환율제도"),
Questions(questionText: "다음중 경기 변동에 가장 민감한 것은 어느것인가?", answers: ["물가지수", "환율", "주가지수"], correctAnswer: "주가지수"),
Questions(questionText: "다음중 우리나라 화폐 제도는 어느것인가?", answers: ["관리통화제도", "고정환율제도", "금 본위제도"], correctAnswer: "관리통화제도"),
Questions(questionText: "대한제국 이란 국호를 처음으로 사용하게 된 시기는 언제인가?", answers: ["아관파천 이후", "갑오경장 이후", "을미개혁 이후"], correctAnswer: "아관파천 이후")
]
var numberOfQuestion = 0
var score = 0
mutating func checkAnswer(_ userAnswer: String) -> Bool {
if userAnswer == quiz[numberOfQuestion].correctAnswer {
score += 1
return true
} else {
return false
}
}
func getScore() -> Int {
return score
}
func getAnswerList() -> [String] {
return quiz[numberOfQuestion].answers
}
func UpdateQuestionText() -> String {
return quiz[numberOfQuestion].questionText
}
func updateProgressBar() -> Float {
let progress = Float(numberOfQuestion + 1) / Float(quiz.count)
return progress
}
mutating func nextQuestion() {
if numberOfQuestion + 1 < quiz.count {
numberOfQuestion += 1
} else {
numberOfQuestion = 0
score = 0
}
}
}
완성 파일
---------- 문법 ----------
Struct
struct town {
let name: String = "서근"
let myFamily = ["서근", "미진", "희진", "초코"]
let description = ["서근": 27, "미진": 19, "희진": 29, "초코": 6]
}
// struct를 사용할 수 있게 이니셜라이즈 해줌.
var myTown = town()
print(myTown.name)
print("제 이름은 \(myTown.name)이고, 나이는 \(myTown.description["서근"]!)세입니다.")
append
myTown.myFamily.append("루키")
print(myTown.myFamily) //["서근", "미진", "희진", "초코", "루키"]
method
struct
또는 class
의 중괄호 안에 func
함수 키워드가 있다면 그것은 메서드이다.
struct town {
let name: String = "서근"
var myFamily = ["서근", "미진", "희진", "초코"]
let description = ["서근": 27, "미진": 19, "희진": 29, "초코": 6]
func someMethod() {
print("struct안에 func키워가 있다면 그것은 메서드 이다.")
}
}
var myTown = town()
//town의 메서드 호출
myTown.someMethod() //struct안에 func키워가 있다면 그것은 메서드 이다.
이것을 자동차로 비유해보자면
Property
- 자동차의 색, 자동차의 브랜드 등을 나타냄
Method
- 자동차를 전진, 후진, 브레이크, 비상등 등을 실행하도록 구현함
init()
위처럼 struct
를 생성했지만 이것들을 바로 호출할 수 없다. 이 구조체를 호출하기 위해서는 초기화 즉, 이니셜라이저 해야 한다.
목적 : 블루프린트 같은 struct
를 복사해서 사용하기 위함
예를 들어 이러한 도표 위해 자동차를 그렸다고 생각하면 이제 이 자동차를 실제 객체로 바꿔야 한다.
struct town {
let name: String
var family: [String]
let description: [String: Int]
init(name: String, myFamily: [String], description: [String: Int]) {
self.name = name
self.family = myFamily
self.description = description
}
func someMethod() {
print("struct안에 func키워가 있다면 그것은 메서드 이다.")
}
}
var myTown = town(name: "서근", myFamily: ["미진", "초코", "희진"], description: ["미진": 19, "희진": 29, "초코": 6])
myTown.family.append("루키")
print(myTown.family) //["미진", "초코", "희진", "루키"]
var ghostTown = town(name: "처녀귀신", myFamily: [], description: ["달걀귀신": 100, "처녀귀신": 120])
ghostTown.someMethod() // struct안에 func키워가 있다면 그것은 메서드 이다.
Challenge - 1
[Coding Exercise] Structures
You are about to create the next big social networking app, exclusive to business leaders called KingPin.
Define a Structure
As part of this app, you need to define a struct called User to represent a user.
This struct needs to hold onto the user's name, email (optional), number of followers, and whether they are active or not. The User struct needs to have the properties:
- name
- email?
- followers
- isActive
The Struct also needs to have a method called logStatus(). If the user is active, the method needs to print "XXX is working hard". Otherwise, it needs to print "XXX has left earth" (where XXX is the name of the user).
Initialise the Structure
After you have defined the struct, create a user with the name "Richard" with 0 followers who not active. Then print the status of this user to the console with logStatus().
<hide/>
// Define the User struct here
struct User {
var name: String
var email: String?
var followers: Int
var isActive: Bool
init(name: String, email: String?, followers: Int, isActive: Bool) {
self.name = name
self.email = email
self.followers = followers
self.isActive = isActive
}
func logStatus() {
if isActive == true {
print("\(name) is working hard")
} else {
print("\(name) has left earth")
}
}
}
// Initialise a User struct here
let user = User(name: "Richard", email: nil, followers: 0, isActive: false)
user.logStatus()
Design Pattern
Design pattern : 문제를 해결하기 위한 수단
MVC Design Pattern
Model과 View를 분리시킨 이유
- viewController
와 View(Main.storyboard)
는 수정하지 않고 Model
만 변경시키면 앱의 디자인을 변경할 수 있다.
- JAVA
로 MVC
디자인 패턴을 만들었을 땐 viewController
에서 기능을 구현하고 Model
에서는 쿼리문을 작성하고 뷰에서는 값을 뿌렸었는데 Swift
에서는 조금 다르다.
- MVC
디자인 패턴은 재사용에 아주 좋다.
- 또 다른 디자인 패턴
- VIPER
- MVVM ( 가장 많이 사용함 )
IBOutlet 조작법
viewController
에 있는 @IBOutlet
을 조작하려면 function
의 return
값을 활용하면 된다.
Functions with Outputs and Return Types
함수의 매개변수와 매개 변숫값이 Input이고 ->
으로 반환하는 타입을 output이라고 한다. 반환하는 값 output은 return
하는 타입과 반드시 일치해야 한다.
func greeting1() {
print("안녕하세요")
}
greeting1() //안녕하세요
/* =================== */
func greeting2(_ name: String) {
print("\(name)씨 안녕하세요")
}
greeting2("서근") //서근씨 안녕하세요
/* =================== */
func greeting3(name: String) -> String {
if name == "서근" || name == "미진" {
return "안녕하세요 \(name)씨"
} else {
return "...누구시죠?"
}
}
print(greeting3(name: "서근")) //안녕하세요 서근씨
print(greeting3(name: "미진")) //안녕하세요 미진씨
let greetingTo = greeting3(name: "초코")
print(greetingTo) //...누구시죠?
/* =================== */
func greeting4(_ name: String) -> Bool {
if name == "서근" {
return true
} else {
return false
}
}
print(greeting4("서근")) //true
print(greeting4("미진")) //false
Challenge - 2
Using what you have learnt about functions which can have outputs, create a function called isOdd(n: Int).
For any given whole number passed to the function, e.g.
- isOdd(n: 5)
The function will test to see if the number is odd. If it is, then it should output true otherwise it should output false. These are Booleans and not Strings.
NOTE: You should not write any print statements. The tests will only pass if the result is an output.
func isOdd(n: Int) -> Bool {
if n % 2 != 0 {
return true
} else {
return false
}
}
혹은 삼항연산자를 사용해서
func isOdd(n: Int) -> Bool {
return n % 2 != 0 ? true : false
}
immutable 변경 불가성 (Mutating)
- let
keyword
- old copy
를 destroy
하고 new copy
를 만들어야 한다. (예전의 것을 깨부수고, 새로운 것을 만든다)
- struct
변경
1. outside와 inside에서 구조체를 변경하는 것에는 차이가 있다.
2. inside 안에서 변경할 때, 'self' is immutable
오류가 발생하는데 inside에서의 self
는 let
키워드이다.
3. inside내에서 구조체의 속성을 변경하려 했기 때문에 self
는 immutable
(변경 불가성 let
)이라는 오류 메시지를 띄움.
4. mutating
을 붙여주면 self.description
이 var description
처럼 작동해 상태를 변경할 수 있다
읽어주셔서 감사합니다 🤟
'SWIFT > Udemy iOS' 카테고리의 다른 글
[Udemy] 섹션11: Segue, Cocoa Touch Class, Optional Binding, BMI계산기 (0) | 2021.08.09 |
---|---|
[Udemy] 섹션 10: iOS App Design Pattern Challenge (0) | 2021.08.05 |
[Udemy] 섹션8: Egg Timer / ProgressView ( Control Flow and Optionals ) (0) | 2021.07.31 |
[Udemy] 섹션7: Play Sound 및 Bundle - 실로폰 만들기 (0) | 2021.07.30 |
[Udemy] 섹션6: Auto Layout and Responsive UIs (오토레이아웃, 반응형 UI) (0) | 2021.07.30 |