Never타입

Ios_Roy·2023년 3월 5일
0

swift 문법

목록 보기
28/29
post-thumbnail

Never타입

함수의 리턴의 의미

  • 함수의 return의 의미 (일반적인 경우)
  • (함수의 결과로 인한) 값을 리턴
  • 함수 내부로 전달했던 CPU실행의 제어권을 다시 돌려줌
func addTwoNumbers(a: Int, b: Int) -> Int {
    var c = a + b
    return c
}

var num1 = 5
var num2 = 3

var num3 = addTwoNumbers(a: num1, b: num2)
print(num3)

Never타입과 함수의 제어권을 Nonreturning하는 함수들

리턴형이 Never타입인 함수의 이해

func crashAndBurn() -> Never {
    fatalError("앱의 해킹이 발견됨")
}

print("1")
crashAndBurn()
print("2")
  • Nonreturning(논리터닝) 함수:

    • 제어권을 전달하지 않음(함수를 호출했던 코드로 다시 제어권을 전달하지 않음)
  • 명시적으로 제어권을 전달하지 않는다는 것을 표시하기 위해 Never(네버)타입으로 선언

  • Never타입을 리턴하는 함수

  • 1) 함수 내부에서 프로그램을 종료시켜야함(예: fatalError())

  • 2) 항상 에러를 던져서, catch문에서 처리하도록 해야함(제어권을 catch문으로)

  • Never타입 (임시적인 타입)

  • 내부가 빈 열거형으로 선언

  • 인스턴스를 생성할 수 없음(Uninhabited Type)
    예) let day: Weekday = Weekday.monday 이런식의 인스턴스 생성 불가
    또한 let some = Never() 도 안됨 (단순 표시를 위한 타입이라고 봐야함)

  • 왜 사용할까?

  • 런타임(실제 앱 실행중)에 발생할 수 있는 에러를 미리 발견하고, 검증/테스트 하기 위함

  • 앱의 해킹이라는 극단적인 예를 들었지만, 실제로 앱의 해킹이 아닌 조금 가벼운 에러라면
    실제 앱을 출시(release)시에는 해당 코드를 삭제하여야함
    (삭제하지 않으면 앱이 꺼질 가능성이 높기 때문에 사용자에게 사용성이 안 좋은 앱으로
    평가받을 가능성이 높음)

에러를 던지는 Never타입 함수의 예시

// 1) 에러 정의
enum SomeError: Error {
    case aError
    case bError
}

// 2) 에러를 던지는 함수의 정의

func someThrowingErrorFuncion() throws -> Never {
    if true {
        throw SomeError.aError
    } else {
        throw SomeError.bError
    }
}

// 3) 에러를 던지는 함수의 실행

do {
    try someThrowingErrorFuncion()
} catch {
    print(error)
}

fatalError( )

fatalError( ) 함수의 이해

 func fatalError(_ *message: @autoclosure () -> String = String(),*
 *file: StaticString =* #file,
line: UInt = #line) -> Never
  • message: (에러발생할때) 표시하려고 하는 메세지
  • file: (에러발생) 파일이름 (기본설정 #file)
  • line: (에러발생) 라인번호 (기본설정 #line)
  • 리턴형: Never 타입
func someCloseAppSituation() {
    fatalError("앱 해킹시도 흔적 발견")
}

//someCloseAppSituation()
// __lldb_expr_4/fatalError.playground:22: Fatal error: 앱 해킹시도 흔적 발견

애플 내부의 구현 - 간단한 예시

var name: String

//print(name)
// fatalError.playground:32:5: note: variable defined here

// 애플 내부에도 많은 함수들이 fatalError로 구현된 경우가 많음

// 빨간 줄을 표시하고, 어떤 치명적 에러가 발생했는지도 알려주며
// ===> 실은 개발자에게 (실제 앱을 출시하기 전에 오류를) 체크하고 수정할 수 있도록 알려주는 것임

// 그럼 우리도 직접 내부에서 동작하는 것처럼
// 필요한 경우에 조건에 따라서, 앱을 종료시키는 에러를 직접 만들 수 있음

디버깅 함수

디버깅(테스트/검증)을 위해 일부러 앱을 중지 시키는 함수

[디버깅(검증) 함수]

  • assert()

  • assertionFailure()

  • precondition()

  • preconditionFailure()

  • fatalError()

  • 앱을 테스트하여서, 런타임동안 발생할 수 있는 여러 버그의 가능성,
    잘못된 코드의 검증 등을 수행하도록 도와주는 함수

  • print() / dump() 일종의 디버깅 함수
    어떤 코드들이 입력되는지, 콘솔창을 통해 확인 / 검증

precondition( ) / preconditionFailure( ) 함수의 사용

  • precondition( ) ➞ 실제앱을 출시시에도, 앱을 의도적으로 종료시켜야하는 상황
  • 유의미하기 때문에, 앱을 일부러 종료해야함
  • 예) 앱의 업데이트로 인해, 버전이 업데이트 되었는데, 이전버전을 계속 깔고 있다면 서버와의 통신이 잘못될 수 있기 일부러 종료시켜야 할 수도 있음
func appUpdateCheck1() {
    let update = false
    precondition(update, "앱을 업데이트 하지 않음")
}

//appUpdateCheck1()

func appUpdateCheck2() {
    let update = false
    
    if update {
        // 앱을 업데이트 했을때, 정상적으로 실행할 코드
        
    } else {
        preconditionFailure("앱을 업데이트 하지 않음")
    }
}

//appUpdateCheck2()

assert( ) / assertionFailure( ) 함수의 사용

  • assert( ) ➞ 실제앱을 출시시, 일부러 앱을 종료시켜야 정도의 상황은 아니지만, 디버그모드에서는 검증 가능
  • 예상하는 범위를 벗어난 결과이지만, 아주 유의미하지는 않아서, 굳이 종료 시키는 것은 안 좋음
  • 예) 레이블에 20 % / 30% /... 100% 표시한다고 했을때, -10%라고 표시된다고 굳이 앱을 종료시켜야 하는가?
func enterWrongValue1() {
    let someWrongInput = -1
    assert(someWrongInput > 0, "유저가 값을 잘못 입력")
}

//enterWrongValue1()

func enterWrongValue2() {
    let someWrongInput = -1
    
    if someWrongInput > 0 {
        // 정상적으로 처리하는 코드
        
    } else {
        assertionFailure("유저가 값을 잘못 입력")
    }
}

//enterWrongValue2()
profile
iOS 개발자 공부하는 Roy

0개의 댓글