연관성 있는 값들을 모아 놓은 것.
enum CompassPoint {
case north
case south
case east, west
}
var direction = CompassPoint.east
direction = .west
switch direction {
case .north: //direction 변수가 north이면
print("north")
case .south:
print("south")
case .east:
print("east")
case .west:
print("west")
}
특정 타입의 값을 원시값으로 가지게 하려면 열거형 오른쪽에 타입 명시하면 된다.
enum CompassPoint2: String {
case north = "북"
case south = "남"
case east = "동"
case west = "서"
}
var direction2 = CompassPoint2.east
switch direction2 {
case .north:
print(direction2.rawValue)
case .south:
print(direction2.rawValue)
case .east:
print(direction2.rawValue)
case .west:
print(direction2.rawValue)
}
원시값으로 열거형을 반환할 수도 있다.
let direction3 = CompassPoint2(rawValue: "남") // south
열거형은 연관값도 가질 수 있다. 각 항목 옆에 소괄호로 묶어 표현이 가능하다.
enum PhoneError {
case unknown
case batteryLow(String)
}
let error = PhoneError.batteryLow("배터리가 곧 방전됩니다.")
// 추출하려면 if case 아니면 switch문
switch error{
case .batteryLow(let message): //연관값 추출
print(message)
case .unknown:
print("알 수 없는 에러")
}
옵셔널에 속해 있는 nil일지도 모르는 프로퍼티, 메서드, 서브스크립션 등을 가져오거나 호출할 때 사용할 수 있는 일련의 과정.
옵셔널에 값이 있다면 프로퍼티, 메소드 등을 호출할 수 있으며, 값이 없다면 nil을 반환한다.
struct Developer {
let name: String
}
struct Company {
let name:String
var developer:Developer?
}
var company1 = Company(name: "Kakao", developer: nil)
print(company1.developer) // nil
var developer = Developer(name: "Shawn")
var company2 = Company(name: "Kakao", developer: developer)
print(company2.developer) // developer 프로퍼티는 옵셔널 타입임 -> optional로 감싸져있음
//print(company2.developer.name) // 에러발생 : 디벨로퍼 옵셔널이 언래핑되어야 한다는 메세지
print(company2.developer?.name) // ? : 접근한 프로퍼티의 값은 옵셔널로 감싸져있음. 값이 nil일 수도 있어서. 벗겨내고 싶다면 옵셔널 바인딩
print(company2.developer!.name) // ! : 강제 언래핑
에러 처리 : 프로그램 내에서 에러가 발생한 상황에 대해 대응하고 이를 복구하는 과정
에러 처리 과정 : 발생(throw) -> 감지(catching) -> 전파(propagating) -> 조작(manipulating)
// 열거형을 통해 오류를 표현하는 것이 일반적
enum iPhoneError:Error { // 에러프로토콜 채택
case unknown
case batteryLow(batteryLevel:Int)
}
throw iPhoneError.batteryLow(batteryLevel: 20) // 에러가 발생할 것 같은 지점에 에러를 던져줌 // 실제로 에러 발생.
do {
try 오류 발생 가능 코드
} catch 오류 패턴 {
처리 코드
}
func checkPhoneBatteryStatus(batteryLevel:Int) throws -> String { // throwing 함수. 함수의 반환값이 있다면 이와 같이 Throw 키워드 뒤에 반환값
guard batteryLevel != -1 else { throw iPhoneError.unknown} // -1이면 else구문 실행 -> iPhoneError를 발생
guard batteryLevel > 20 else { throw iPhoneError.batteryLow(batteryLevel: 20)}
return "배터리 상태가 정상입니다."
}
do {
try checkPhoneBatteryStatus(batteryLevel: 20)
} catch iPhoneError.unknown {
print("알 수 없는 에러")
} catch iPhoneError.batteryLow(let batteryLevel){
print("배터리 부족. 남은 배터리 : \(batteryLevel)")
} catch {
print("그 외 오류 발생 : \(error)")
}
let status = try? checkPhoneBatteryStatus(batteryLevel: -1) // unknown을 던져주기 때문에 status 상태가 nil
print(status) // 출력값 : nil
let status2 = try? checkPhoneBatteryStatus(batteryLevel: 34)
print(status2) // 출력값 : Optional(배터리 상태 정상)
let status3 = try? checkPhoneBatteryStatus(batteryLevel: 19)
print(status3) // nil
let status4 = try! checkPhoneBatteryStatus(batteryLevel: -1)
print(status4) // 오류발생!
코드에서 전달 및 사용할 수 있는 독립 기능 블록. 일급 객체의 역할 가능
일급 객체 : 전달인자로 보낼 수 있고, 변수/상수 등으로 저장하거나 전달할 수 있으며, 함수의 반환 값이 될 수도 있다.
보통 Unnamed Closure를 지칭함.
형식 :
{(매개변수) -> 리턴타입 in
실행구문
}
let hello = { () -> () in // 파라미터와 리턴타입 둘 다 없다
print("hello")
}
hello()
let hello2 = { (name:String) -> (String) in
return "Hello, \(name)"
}
//hello2(name:"Shawn") // 에러 : 전달인자 레이블을 적지 않고 파라미터 값 넘겨줘야
hello2("Shawn")
func doSomething(closure: () -> ()) {
closure() // dosomething이 호출되면 closure 실행되게
}
doSomething(closure: {() -> () in
print("hello~~")
})
func doSomething2() ->() -> () {
return { () -> () in
print("hello4")
}
}
doSomething2()()
func doSomething(closure: () -> ()) {
closure() // dosomething이 호출되면 closure 실행되게
}
doSomething(closure: {() -> () in
print("hello~~")
})
를
doSomething(){
print("closure too long")
}
doSomething{ // 소괄호도 생략 가능
print("closure too long")
}
로!
func multipleClosure(success:() -> (), fail: () -> (), neutral:() -> ()){
}
multipleClosure {
<#code#>
} fail: {
<#code#>
} neutral: {
<#code#>
}
func doSomething3(closure:(Int, Int, Int) -> Int){
closure(1,2,3)
}
doSomething3(closure:{(a, b, c) in // 표현 간소화하지 않은 Full version
return a+b+c
})
doSomething3(closure: { // 데이터타입 생략. 약식인수 사용
return $0+$1+$2
})
doSomething3(closure: { // 단일 리턴문일경우 리턴타입 생략. 아무것도 다른게 없을 때 가능
$0+$1+$2
})
doSomething3(){ // 후행클로저 표현으로
$0+$1+$2
}
doSomething3{ // 클로저가 단 하나만일때
$0+$1+$2
}
다른 함수를 전달인자로 받거나 함수 실행의 결과를 함수로 반환하는 함수이다.
swift 함수는 일급객체 -> 함수의 전달인자로 전달 가능하며, 함수의 결괏값으로 반환할 수도 있다.
스위프트에서 제공하는 고차함수는 3가지로, map, filter, reduce가 있다.
// map : 컨테이너 내부의 기존 데이터를 변형하여 새로운 컨테이너를 생성한다.
let numbers = [0,1,2,3]
let mapArray = numbers.map{(number) -> Int in
return number*2
}
print("map \(mapArray)")
// filter : 컨테이너 내부의 값을 걸러서 새로운 컨테이너로 추출.
let intArray = [1, 3, 20, 156, 4]
let filterArray = intArray.filter { $0 > 5}
print("filter \(filterArray)")
// reduce : 컨테이너 내부의 요소를 하나로 통합시켜줌.
let someArray = [1,2,3,4,5]
let reduceResult = someArray.reduce(0) { // 초기값을 0으로 설정. result는 누적값을 뜻하고, element는 배열의 요소를 뜻함. 초기값이 0이 아닌2라면 15가 아닌 17이 됨.
(result: Int, element: Int) -> Int in
print("\(result) + \(element)")
return result+element
}
print("reduce \(reduceResult)")
let reduceResult2 = someArray.reduce(0){
$0-$1
}
print("reduce2 \(reduceResult2)")