티스토리 뷰

Swift&IOS

rethrows

밀쿄 2020. 1. 9. 17:15

안녕하세요. 밀쿄입니다.

오늘은 rethrows에 대해서 알아보겠습니다.

rethrows에 대해 설명하기 위해서는 throws에 대해서 먼저 설명하겠습니다.

 

다음과 같은 코드가 있습니다.

오늘 이 코드로 우려먹을꺼지만 코드에 억지가 많습니다 참고부탁드립니다.

enum EnterResult {
    case noWaitingLine
    case accept
    case reject
}
protocol WaitingLineProtocl {
    associatedtype WaitingLine = [String: Ticket]
}
struct Movie: WaitingLineProtocl {
    private var name: String
    
    public init(name: String) {
        self.name = name
    }
    
    func isVaild(_ waitingLine: WaitingLine) -> Bool {
        guard let _ = waitingLine[self.name] else {
            return false
        }
        
        return true
    }
}
struct Ticket {
    private var movieName: String
    
    public init(movieName: String) {
        self.movieName = movieName
    }
}

class Theater: WaitingLineProtocl {

    private var waitingLine: WaitingLine
    
    init(waitingLine: WaitingLine) {
        self.waitingLine = waitingLine
    }
    
    func enter(_ movie: Movie) -> EnterResult {
        
        if waitingLine.count == 0 {
            return .noWaitingLine
        }
            
        else if movie.isVaild(self.waitingLine) {
            self.waitingLine.popFirst()
            return .accept
        }
        
        self.waitingLine.popFirst()
        return .reject
    }
}

위 코드는 현재 throw가 없습니다.

하지만 다음과 같은 코드는 작동합니다.

let theater = Theater(waitingLine: ["저승사자와함께": Ticket(movieName: "저승사자와함께")])
var movie = [Movie(name: "저승사자와함께"), Movie(name: "나홀로")]
movie.compactMap(theater.enter(_:)).map { results in
    switch  results {
    case .noWaitingLine:
        print("관객 없습니다")
    case .accept:
        print("입!장!")
    case .reject:
        print("돌아가!")
    }
}
//결과
//입!장!
//관객 없습니다

compactMap의 선언부를 잠깐 살펴보겠습니다.

func compactMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult

그렇습니다. compactMap은 Error를 던질 수 있는 throws함수입니다.

즉 이것을 통해 Error를 던지지 않는 함수는 Error를 던질 수 있는 throws함수와 하위 호환이 된다는 점을 알 수 있습니다.

반대의 경우는 어떨까요?

반대의 경우는 성립하지 않습니다.

enum ResultError: Error {
    case noAudience
}

func resultSelector(_ enterResult: EnterResult) throws -> String {
    if enterResult == .noWaitingLine {
        throw ResultError.noAudience
    }
    
    switch enterResult {
    case .accept:
        return "입!장!"
    case .reject:
        return "돌아가!"
    case .noWaitingLine:
        return ""
    }
}

func resultSelectorCaller(resultSelector: (EnterResult) -> String) {
    print(resultSelector(.noWaitingLine))
}

resultSelectorCaller(resultSelector: resultSelector)
//에러발생
//Invalid conversion from throwing function of type '(EnterResult) throws -> String' to non-throwing function type '(EnterResult) -> String'

위에 오류를 고쳐보도록 하겠습니다.

func resultSelectorCaller(resultSelector: (EnterResult) throws -> String) {
    do {
        print(try resultSelector(.noWaitingLine))
    } catch {
        print(error)
    }
}

resultSelectorCaller(resultSelector: resultSelector)
//결과
//noAudience

이걸 조금 더 간결하게 줄여보겠습니다.

func resultSelectorCaller(resultSelector: (EnterResult) throws -> String) rethrows {
    print(try resultSelector(.noWaitingLine))
}

do {
    try resultSelectorCaller(resultSelector: resultSelector(_:))
} catch {
    print(error)
}
//결과
//noAudience

rethrows를 쓰면 이렇게 쓸 수 있습니다.

보기에는 throw와 비슷해보이지만 rethrows는 매개변수로 전달받은 함수가 에러를 던질 때 사용하게 됩니다.

매개변수에서 전달받은 함수 중에 최소 한개의 함수가 에러를 던질 때 사용 가능합니다

 

참고했던 자료입니다.
https://docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html

 

Error Handling — The Swift Programming Language (Swift 5.1)

Error Handling Error handling is the process of responding to and recovering from error conditions in your program. Swift provides first-class support for throwing, catching, propagating, and manipulating recoverable errors at runtime. Some operations aren

docs.swift.org

https://redsubmarine.github.io/2016/10/21/Swift-3.0-의-throws,-rethrows-에-대하여....html

 

Swift 3.0 의 throws, rethrows 에 대하여...

반년전즈음 스터디모임에서 Swift 3.0의 Array 에 대해 다루다가 map 이라는 함수를 보고 의문점이 생겼다. 분명히 내가 기억하기로는 Swift 2.2에서 Array의 map 함수는 Array.map(transform: T -> U) 이와 같이 생겼던걸로 기억한다. 이랬던 map이 Swift 3.0에서 형태가 바뀌었다. map(_ transform: (Element) throws -> T) rethrows -> [T] Swift 2.0 에서 do

redsubmarine.github.io

 

'Swift&IOS' 카테고리의 다른 글

UIWindow  (1) 2020.01.13
flatMap, compactMap  (0) 2020.01.10
StackView + ScrollView  (0) 2020.01.02
translatesAutoresizingMaskIntoConstraints  (0) 2019.12.30
[AutoLayout] leading, trailing, left, right  (0) 2019.12.26
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함