옵셔널 체이닝

옵셔널에 속해있는 nil일지도 모르는 프로퍼티, 메서드, 서브스크립션 등을 가져오거나 호출할 때 사용할 수 있는 일련의 과정을 옵셔널 체이닝이라고 한다. 이는 옵셔널 바인딩을 사용하지 않고 옵셔널 값에 접근하기에 매우 유용한 수단이 된다.

struct Developer {
	let name: String
}

struct Company {
	let name: String
	var developer: Developer?
}

var company = Company(name: "Gunter", developer: nil)
print(company.developer)
// nil

var developer = Developer(name: "Han")
var company = Company(name: "Gunter", developer: developer)
print(company.developer)
// Optional(__lldb_expr_587.Developer(name: "Han"))

여기서, 옵셔널한 developername 속성에 접근하려고 하면 당연히 에러가 발생한다. 이때 이를 회피하기 위해 ?를 사용하거나 !를 사용하여 옵셔널 체이닝을 구사할 수 있다.

print(company.developer.name)
// Error! Value of optional type 'Developer?' must be unwrapped to refer to member 'name' of wrapped base type 'Developer'....

print(company.developer?.name)
// Optional("Han")

print(company.developer!.name)
// "Han"

try...catch

Swift는 런타임에 에러가 발생(throwing)할 경우, 감지(catching), 전파(propagating), 조작(manipulating)의 처리를 지원하는 헬퍼 클래스를 지원한다.

에러 프로토콜(Error)과 throw를 이용한 에러발생

enum PhoneError: Error {
	case unknown
	case batteryLow(batteryLevel: Int)
}

throw PhoneError.batteryLow(batteryLevel: 20)
// Playground execution terminated: An error was thrown and was not caught:
// PhoneError
//	batteryLow : 1 element
//		- batteryLevel : 20

함수에서 발생한 오류를 do..catch 구문을 이용하여 해당 함수에 전파

func checkPhoneBatteryStatus(batteryLevel: Int) throws -> String {
	guard batteryLevel != -1 else { throw PhoneError.unknown }
	guard batteryLevel > 20 else { throw
		PhoneError.batteryLow(batteryLevel: 20)
	}
	return "배터리 상태가 정상입니다"
}

do {
	try checkPhoneBatteryStatus(batteryLevel: -1)
} catch PhoneError.unknown {
	print("알 수 없는 에러입니다.")
} catch PhoneError.batteryLow(let batteryLevel) {
	print("배터리 전원 부족.. 남은 배터리: \(batteryLevel)%")
} catch {
	print("그 외 오류 발생: \(error)")
}
// "알 수 없는 에러입니다."

do {
	try checkPhoneBatteryStatus(batteryLevel: 19)
} catch PhoneError.unknown {
	print("알 수 없는 에러입니다.")
} catch PhoneError.batteryLow(let batteryLevel) {
	print("배터리 전원 부족.. 남은 배터리: \(batteryLevel)%")
} catch {
	print("그 외 오류 발생: \(error)")
}
// "배터리 전원 부족.. 남은 배터리: 19%"

함수에서 발생한 오류를 try?, try! 키워드를 이용하여 해당 함수에 전파

let status1 = try? checkPhoneBatteryStatus(batteryLevel: -1)
print(status1)
// nil

let status2 = try? checkPhoneBatteryStatus(batteryLevel: 30)
print(status2)
// Optional("배터리 상태가 정상입니다")

let status3 = try! checkPhoneBatteryStatus(batteryLevel: 30)
print(status3)
// "배터리 상태가 정상입니다"

let status4 = try! checkPhoneBatteryStatus(batteryLevel: -1)
print(status4)
// __lldb_expr_643/example.playground:38: Fatal error: 'try!' expression unexpectedly raised an error...
profile
전직 시스템엔지니어, 현직 데이터엔지니어, 하지만 하고 싶은건 iOS 개발

0개의 댓글