궁금한 내용을 검색해보세요!
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
서근 개발노트
티스토리에 팔로잉
SWIFT/Udemy iOS

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 )

서근
QUOTE THE DAY

“ 컴퓨터 시스템 분석은 아이 양육과 같다. 견딜 수 없는 피해를 줄 순 있어도 성공을 보장할 순 없다. ”

- 톰 드마르코 (Tom DeMarco)
Written by SeogunSEOGUN

 

목표 : MVC 패턴에 대해 알아본다.

Quizzler Project

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 )

main storyboard elementsviewController로 연결해준다.

swift
UNFOLDED
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이다. 만약 앱을 실행하자마자 퀴즈의 텍스를 보여주려면 다음과 같이 퀴즈 배열을 작성하고 이 코드 안에 다음과 같이 작성하면 된다.

swift
UNFOLDED
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. PressedAnswerBtnnumberOfQuestion + 1 추가

 

문제점 viewDidLoad는 앱이 실행될 때 단 한 번만 업데이트하기 때문에 questionLabelButtonpress 되었을 때도 업데이트돼야 한다.

 

해결방법 UpdateUI 함수를 만들어 호출

swift
UNFOLDED
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

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - 1D / 2D Array
[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - 1D / 2D Array

1D Array 검색

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - 1D / 2D Array - 1D Array 검색

2D Array 검색

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - 1D / 2D Array - 2D Array 검색

연습

만약 2D Array에서 다음과 같은 배열이 있을 때 숫자 9를 프린트하려면 다음과 같다.

swift
UNFOLDED
let twoDArray = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
print(twoDArray[2][2]) //9

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - 1D / 2D Array - 연습

Quiz 배열 수정

swift
UNFOLDED
let quiz = [
["달걀은 어린 닭이 낳은 것일수록 그 크기가 크다", "False"],
["달걀은 뾰족한 쪽에 호흡하는 공간이 있어서 둥근 쪽을 아래로 해서 보관해야 합니다", "False"],
["꺼벙이란 꿩의 새끼를 말합니다", "Ture"],
["외출 전에 자외선 차단제를 바르면 햇볕을 오래 받아도 무방하다", "Fasle"]
]
...
func updateUI() {
questionLabel.text = quiz[numberOfQuestion][0] // 2D Array
}
}

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - Quiz 배열 수정

Quiz 정답 버튼 구현

정확한 정답을 눌렀을 때를 구별하기 위한 코드를 구현해야 한다.

 

1. userAnswer 상수 생성 > sender.currentTitle

2. currentAnswer 상수 생성 > quiz의 numberOfQuestion 배열의 [1](true or false) 할당

3. if문을 사용하여 정답 혹은 오답 프린트

4. numberOfQuestionquiz.count 보다 작으면 +1을 더해줌

문제점 여전히 quiz의 질문이 끝나면 앱이 크래쉬 됨.

해결방법 만약 numberOfQuestion가 4이면 quiz.count가 4이기 때문에 다음 버튼을 눌렀을 때 앱이 크래쉬 난다. 그렇기 때문에 처음부터 numberOfQuestion+1을 하고 조건문을 작성하면 해결된다.

5. else문에 numberOfQuestion을 0으로 정해주어 퀴즈가 끝나도 계속 반복될 수 있도록 해준다.

swift
UNFOLDED
@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에 대한 문법

swift
UNFOLDED
// 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 함수 수정

swift
UNFOLDED
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
}
}
swift
UNFOLDED
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. ButtoncornerRadiusviewDidLoad안에서 수정해준다.

swift
UNFOLDED
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 문법 

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - MVC 패턴으로 코드 정리 - New Group from Selection

Model (QuizBrain.swift 생성)

QuizBrain Model을 구조체로 만들고 viewController에 있던 코드를 가져오고 몇 가지 메서드를 만들어줘야 한다. 또, UpdateUI 부분에 오류 부분도 수정해줘야 한다. 에러난 두 부분을 QuizBrain에 메서드로 만들어서 해결해줄 수 있다.

swift
UNFOLDED
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
}
swift
UNFOLDED
// 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
}
}
swift
UNFOLDED
//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)이 오류가 생긴 것을 확인할 수 있다.

swift
UNFOLDED
// 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 문법

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - MVC 패턴으로 코드 정리 - mutating

문제점 그럼 이러한 오류가 발생하는데, selfimmutable(변경 불가성) 이기 때문에 사용이 불가능하다고 한다.

 

해결방법 func 키워드 앞에 mutating 키워드 사용

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - MVC 패턴으로 코드 정리 - mutating

updateProgressBar 메서드와 nextQuestion 메서드의 차이점을 보면 

updateProgressBar - 아무것도 변경하지 않고 progress의 값만 변경

nextQuestion - QuizBrain의 속성을 변경

 

그렇기 때문에 nextQuestion 메서드를 Mutating 키워드를 사용하여 속성이 변경 가능하게 만들어 준 것이다.

완성 파일

Quizzler.zip
0.98MB

객관식 퀴즈 형태로 변경

위에서는 O, X 퀴즈로 두 가지 중 하나만 고를 수 있었는데 객관식으로 변경하려면 코드를 조금 변경해야 한다.

1. 객관식 레이블 추가

2. @IBOutlet 연결

3. QuizBrain 객관식 문제 수정 및 getAnswerList 메서드 추가

4. viewController updateUI 함수에 getAnswerListlet 으로 가져옴

5. UIButton의 텍스트 업데이트는 .text 가 아닌 .setTitle(String, for: )을 사용함

완성 코드

Controller

swift
FOLDED

Model

swift
FOLDED
swift
FOLDED

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - MVC 패턴으로 코드 정리 - Model

완성 파일

Quizzler-MultipleChoice.zip
0.99MB

----------  문법  ----------

Struct

swift
UNFOLDED
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

swift
UNFOLDED
myTown.myFamily.append("루키")
print(myTown.myFamily) //["서근", "미진", "희진", "초코", "루키"]

method

struct 또는 class의 중괄호 안에 func 함수 키워드가 있다면 그것은 메서드이다.

swift
UNFOLDED
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키워가 있다면 그것은 메서드 이다.

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - method

이것을 자동차로 비유해보자면 

Property - 자동차의 색, 자동차의 브랜드 등을 나타냄

Method  -  자동차를 전진, 후진, 브레이크, 비상등 등을 실행하도록 구현함

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - method

init()

위처럼 struct를 생성했지만 이것들을 바로 호출할 수 없다. 이 구조체를 호출하기 위해서는 초기화 즉, 이니셜라이저 해야 한다.

목적 : 블루프린트 같은 struct를 복사해서 사용하기 위함

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - init()

예를 들어 이러한 도표 위해 자동차를 그렸다고 생각하면 이제 이 자동차를 실제 객체로 바꿔야 한다.

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - init()

swift
UNFOLDED
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().

swift
FOLDED

Design Pattern

Design pattern : 문제를 해결하기 위한 수단

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - Design Pattern

MVC Design Pattern

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - Design Pattern - MVC Design Pattern
[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - Design Pattern - MVC Design Pattern

Model과 View를 분리시킨 이유

- viewController와 View(Main.storyboard)는 수정하지 않고 Model만 변경시키면 앱의 디자인을 변경할 수 있다.

- JAVAMVC 디자인 패턴을 만들었을 땐 viewController에서 기능을 구현하고 Model에서는 쿼리문을 작성하고 뷰에서는 값을 뿌렸었는데 Swift에서는 조금 다르다.

- MVC 디자인 패턴은 재사용에 아주 좋다.

  • 또 다른 디자인 패턴
    • VIPER
    • MVVM ( 가장 많이 사용함 )

TIP
 
 

IBOutlet 조작법
viewController에 있는 @IBOutlet을 조작하려면 functionreturn값을 활용하면 된다.

 

Functions with Outputs and Return Types

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - Functions with Outputs and Return Types

함수의 매개변수와 매개 변숫값이 Input이고 ->으로 반환하는 타입을 output이라고 한다. 반환하는 값 outputreturn 하는 타입과 반드시 일치해야 한다.

swift
UNFOLDED
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.

  1. 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.

swift
UNFOLDED
func isOdd(n: Int) -> Bool {
if n % 2 != 0 {
return true
} else {
return false
}
}

혹은 삼항연산자를 사용해서

swift
UNFOLDED
func isOdd(n: Int) -> Bool {
return n % 2 != 0 ? true : false
}

immutable 변경 불가성 (Mutating)

 - let keyword

 - old copydestroy 하고 new copy를 만들어야 한다. (예전의 것을 깨부수고, 새로운 것을 만든다)

- struct 변경

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - immutable 변경 불가성 (Mutating)

1. outsideinside에서 구조체를 변경하는 것에는 차이가 있다.

2. inside 안에서 변경할 때, 'self' is immutable 오류가 발생하는데 inside에서의 selflet 키워드이다.

3. inside내에서 구조체의 속성을 변경하려 했기 때문에 selfimmutable(변경 불가성 let)이라는 오류 메시지를 띄움.

4. mutating을 붙여주면 self.descriptionvar description처럼 작동해 상태를 변경할 수 있다

[Udemy] 섹션9: MVC 패턴, Struct, mutating ( 퀴즈 앱 ) - immutable 변경 불가성 (Mutating)

 

 

읽어주셔서 감사합니다 🤟

 

 


잘못된 내용이 있으면 언제든 피드백 부탁드립니다.


서근


위처럼 이미지 와 함께 댓글을 작성할 수 있습니다.