상현에 하루하루
All 개발자의 하루

스위프트 입문 3일차

( 업데이트: )

익스텐션?

기존의 클래스, 구조체, 열거형, 프로토콜에 새로운 기능을 추가하는 기능

  • 연산 타입 프로퍼티 / 연산 인스턴스 프로퍼티
  • 타입 메서드 / 인스턴스 메서드
  • 이니셜라이저
  • 서브스크립트
  • 중첩 타입
  • 특정 프로토콜을 준수할 수 있도록 기능 추가

연산 프로퍼티가 제일 많이 사용됨

extension Int {
    var isEven: Bool {
        return self % 2 == 0
    }

    var isOdd: Bool {
        return self % 2 == 1
    }
}

var number = 3
number.isOdd // true
number.isEven  // false
extension String {
    func convertToInt() -> Int? {
        return Int(self)
    }
}

var string = "0"
string.convertToInt() // Int(0)

열거형

연관성이 있는 값을 모아 놓은 것을 말한다.
ex) 계절

// 대문자로 시작해야함
enum CompassPoint {
    // 한줄로도 가능
    // case north, south, east, west
    case north
    case south
    case east
    case west
}

var direction = CompassPoint.east
direction = .west // 열거형 이름을 추론해서 내부 이름을 바로 찾을 수 있음

switch direction {
case .north:
    print("north")
case .south:
    print("south")
case .east:
    print("east")
case .west:
    print("west")
}

원시값을 가지게 구성할 수 도있다.

enum CompassPoint: String {
    case north = "북"
    case south = "남"
    case east = "동"
    case west = "서"
}

switch direction {
case .north:
    print(direction.rawValue)
case .south:
    print(direction.rawValue)
case .east:
    print(direction.rawValue)
case .west:
    print(direction.rawValue)
}

let direction2 = CompassPoint(rawValue: "남")

열거형의 연관값

enum PhoneError {
    case unknown
    case batteryLow(String)
}

let error = PhoneError.batteryLow("배터리가 곧 방전됩니다.")

switch error {
case .batteryLow(let message):
    print(message)
case .unknown:
    print("알 수 없는 에러입니다.")
}

옵셔널 체이닝

옵셔널에 속해 있는 nil 일지도 모른느 프로퍼티, 메서드, 서브스크립션 등을 가져오거나 호출할 때 사용할 수 있는 일련의 과정

struct Developer {
    let name: String
}

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

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

var developer = Developer(name: "han");
var company = Company(name: "Gunter", developer: developer)
print(company.developer.name)
// 옵셔널이기때문에 옵셔널을 벗겨야한다. 그런데 이 방법은 번거롭고 다른 방법이 추가적으로 있다
print(company.developer?.name) // nil 이 될 수 도있으므로 error
print(company.developer!.name)

에러처리

1급 클래스를 지원함

  • 발생 (throwing)
  • 감지 (catching)
  • 전파 (propagating)
  • 조작 (manipulating)

에러프로토콜 채택한 열거형

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

throw PhoneError.batteryLow(batteryLevel: 20)

오류를 처리하는 방법

  • 함수에서 발생한 오류를 해당 함수에 전달
function checkPhoneBatteryStatus(batteryLevel: Int) throws -> String { // 반환값이 있다면 throws -> 반환 형
    guard batteryLevel != -1 else { throw PhoneError.unknown }
    guard batteryLevel >= 20 else { throw PhoneError.batteryLow(batteryLevel: 20) }
    return "배터리 상태가 정상입니다."
}

// 위함수는 오류를 던져줄 수도있기 때문에
/*
do {
    try 오류 발생 가능 코드
} catch 오류 패턴 {
    처리코드
}
*/

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

let status2 = try! checkPhoneBatteryStatus(betteryLevel: 30)
print(status2)

try!는 에러를 내지 않는 것을 개발자 확실하게 알수있다면 사용한다 하지만 에러를 내면 애플리케이션이 종료된다.