[부스트코스] iOS 프로그래밍을 위한 스위프트 기초 #3

백승호·2020년 8월 12일
0

링크: https://www.edwith.org/boostcamp_ios/


28. 오류처리

오류를 표현하는 방법은 에러 프로토콜을 사용한다!
주로 열거형을 통해 오류를 표현한다

enum 오류이름: Error {
	case 종류1
	case 종류2
	case 종류3
 ...
}

// 자판기 동작 오류의 종류를 표현한 vendingMachineError
enum VendingMachineError: Error {
	case invalidInput
	case insufficientFunds(moneyNeeded: Int) //열거형의 연관값
	case outOfStock
}
// 오류들은 어떻게 발생시키지?
// 특정 함수안에서 이런 오류가 발생했다는걸 자신을 호출한 함수에
// 오류를 던져준다! throws를 사용해서 오류를 내포하는, 발생할수있는 함수임을 표시한다
class VendingMachine {
	let itemPrice: Int = 100
	var itemCount: Int = 5
	var deposited: Int = 0
	
	func receiveMoney(_ money: Int) throws {
		guard money > 0 else {
			throw VendingMachineError.invalidInput
		}
		self.deposited += money
		print("\(money)원 받음")
	}

	func vend(numberOfItems numberOfItemsToVend: Int) throws -> String {
		guard numberOfItemsToVend > 0 else {
			throw VendingMachineError.invalidInput
		}
		guard numberOfItemsToVend * itemPrice <= deposited else {
			let moneyNeeded: Int
			moneyNeeded = numberOfItemsToVend * itemPrice - deposited

			throw VendingMachineError.insufficientFunds(moneyNeeded: moneyNeeded)
		}
		guard itemCount >= numberOfItemsToVend else {
			throw VendingMachineError.outOfStock
		}
		let totalPrice = numberOfItemsToVend * itemPrice
		self.deposited -= totalPrice
		self.itemCount -= numberOfItemsToVend
		return "\(numberOfItemsToVend)개 제공함"
	}
}

let machine: VendingMachine = VendingMachine()
var result: String?

오류발생 여지가 있는 함수를 사용할 때는 try를 사용해야한다!!!
try, try?, try! 세종류가 있다

do-catch문 활용
do {
	try machine.receiveMoney(0)
} catch VendingMachineError.invalidInput {
		print("입력이 잘못되었습니다")
} catch VendingMachineError.insufficientFunds(let moneyNeeded) {
		print("\(moneyNeeded)원이 부족합니다")
} catch VendingMachineError.outOfStock {
		print("수량이 부족합니다")
}

do {
	try machine.receiveMoney(300)
} catch {
		switch error {
		case VendingMachineError.invalidInput:
			print("입력이 잘못되었습니다")
		case VendingMachineError.insufficientFunds(let moneyNeeded):
			print("\(moneyNeeded)원이 부족합니다")
		case VendingMachineError.outOfStock:
			print("수량이 부족합니다")
		default:
			print("알수없는 오류 \(error)")
		}
}

호출할때마다 [ do try 함수호출 catch 에러케이스 ] 에러케이스 각각에 대해 처리하기 귀찮을수있다
그럴땐 간단하게
do {
	result = try machine.vend(numberOfItems: 4)
} catch {
	print(error)
}

do {
	result = try machine.vend(numberOfItems: 4)
}
이렇게 해도댐!
근데 이것도 깨름칙하잖아 그래서 try? try!가 있음
별도의 오류처리 결과를 통보받지 않고 오류가 발생했으면 결과값을 nil로 돌려받는거야
정상동작후엔 옵셔널 타입으로 정상 반환값을 돌려받을수있다!

result = try? machine.vend(numberOfItems: 2)
result // Optional("2개 제공함")
 // 오류가 발생한다면 nil

result = try! machine.vend(numberOfItems: 1)
result // "1개 제공함" 옵셔널이 아닌 일반타입의 반환값을 돌려받을거야

29. 고차함수

전달인자로 함수를 전달받거나 함수실행의 결과를 함수로 반환하는함수를 말함
map, filter, reduce가있다

map
컨테이너 내부의 기존 데이터를 변형해서 새로운 컨테이너를 생성한다
let numbers: [Int] = [0, 1, 2, 3, 4]

numbers라는 배열의 요소를 어떤 형태로 변환하고 싶다
두배로 변환하거나 문자열로 변환하거나 하고싶다
for구문을 쓰게 되면
각각의 배열을 만들고 기존 배열을 이터레이션하여 구할수있을거야

var doubledNumbers: [Int]
var strings: [String]
doubledNumbers = [Int]()
strings = [String]()

for number in numbers {
	doubledNumbers.append(number * 2)
	strings.append("\(number)")
}

그런데 이렇게 하면 변수를 선언하고 반복문을 돌려야한다는 귀찮음이 발생해

doubledNumbers = numbers.map({ (number: Int) -> Int in
	return  number * 2
})
map의 전달인자 자리에 클로저가 들어와!
어떻게 변환해서 뭘로 돌려줄거냐 지정해줄수있어. 
Int요소 하나하나 받아와서 다시 Int로 반환할거다. 새로운 컨테이너에 넣어달라

strings = numbers.map({ (number: Int) -> String in
	return "\(number)"
})

// 매개변수, 반환 타입, 반환 키워드를 생략한 후행클로저를 사용하면?
doubledNumbers = numbers.map { $0 * 2 }
strings = numbers.map { "\($0)" }
이렇게 간단하게 만들수도 있다!!! 대박이네

filter
컨테이너 내부의 값을 걸러서 새로운 컨테이너로 추출

// for구문 사용시..var 사용
var filtered: [Int] = [Int]()
for number in numbers {
	if number % 2 == 0 {
		filtered.append(number)
	}
}

// filter메소드 사용시..let 사용
let evenNumbers: [Int] = numbers.filter {
	(number: Int) -> Bool in
	return number % 2 == 0
}

// 매개변수, 반환타입, 반환 키워드 생략, 후행클로저
let oddNumbers: [Int] = numbers.filter {
	$0 % 2 != 0
}

reduce
컨테이너 내부 콘텐츠를 하나로 통합
let someNumbers: [Int] = [2, 8. 15]

// for 구문 사용시
var result: Int = 0
for number in someNumbers {
	result += number
}

// reduce 사용시
// 초기값을 지정해주고 
let sum: Int = someNumbers.reduce(0, {
	(first: Int, second: Int) -> Int in
	return first + second
})

let sumFromThree = someNumbers.reduce(3) { $0 + $1 }
profile
삽질하는 개발자 지망생

0개의 댓글