본문 바로가기

개발/iOS

foreach와 for-in에서 탈출방법

Objective-C에서 foreach 구문인 enumarate를 보면 포인터로 stop이 있는 것을 볼 수 있다.

하지만 Swift에서는 stop이 없어져서 루프를 돌다가 탈출하고싶을때 break를 넣어줬는데 swift에서의 break는 for-in이나 Switch같은 정말 루프를 도는 구문에서만 사용가능한 키워드여서 적용이 안된다.

swift의 foreach는 해당 함수내에서 루프를 돌면서 클로저를 실행시키는 형태라 루프가 아니기때문에 break로 탈출이 불가능하다.

그렇다고 해서 return을 쓰면 해당 클로저에서의 return이기때문에 해당 클로저만 종료될뿐 다음 클로저는 계속 실행이 된다.

그래서 굳이 탈출하고 싶으면 do-try-catch로 감싸서 아무에러나 throw해줘야한다.

 

let arr = [1,2,3,4,5,6,7,8]

func forEachReturnTest() {
    print("start")
    arr.forEach {
        print("foreach start: \($0)")
        if $0 == 7 {
            print("foreach return : \($0)")
            return
        }
        print("foreach end : \($0)")
    }
    print("end")
}

func forEachThrowTest() {
    print("start")
    try? arr.forEach {
        print("foreach start: \($0)")
        if $0 == 7 {
            print("foreach return : \($0)")
            throw NSError()
        }
        print("foreach end : \($0)")
    }
    print("end")
}

func forInReturnTest() {
    print("start")
    
    for ar in arr {
        print("forin start: \(ar)")
        if ar == 7 {
            print("forin return : \(ar)")
            return
        }
        print("forin end : \(ar)")
    }
    
    print("end")
}

func forInBreakTest() {
    print("start")
    
    for ar in arr {
        print("forInBreakTest start: \(ar)")
        if ar == 7 {
            print("forInBreakTest return : \(ar)")
            break
        }
        print("forInBreakTest end : \(ar)")
    }
    
    print("end")
}

forEachReturnTest()
print()
forEachThrowTest()
print()
forInReturnTest()
print()
forInBreakTest()
start
foreach start: 1
foreach end : 1
foreach start: 2
foreach end : 2
foreach start: 3
foreach end : 3
foreach start: 4
foreach end : 4
foreach start: 5
foreach end : 5
foreach start: 6
foreach end : 6
foreach start: 7
foreach return : 7
foreach start: 8
foreach end : 8
end

start
foreach start: 1
foreach end : 1
foreach start: 2
foreach end : 2
foreach start: 3
foreach end : 3
foreach start: 4
foreach end : 4
foreach start: 5
foreach end : 5
foreach start: 6
foreach end : 6
foreach start: 7
foreach return : 7
end

start
forin start: 1
forin end : 1
forin start: 2
forin end : 2
forin start: 3
forin end : 3
forin start: 4
forin end : 4
forin start: 5
forin end : 5
forin start: 6
forin end : 6
forin start: 7
forin return : 7

start
forInBreakTest start: 1
forInBreakTest end : 1
forInBreakTest start: 2
forInBreakTest end : 2
forInBreakTest start: 3
forInBreakTest end : 3
forInBreakTest start: 4
forInBreakTest end : 4
forInBreakTest start: 5
forInBreakTest end : 5
forInBreakTest start: 6
forInBreakTest end : 6
forInBreakTest start: 7
forInBreakTest return : 7
end

foreach를 돌다가 그냥 objc처럼 stop을 줘서 탈출하도록 하면 좋을거 같은데 왜 그러지 않을까를 여러 사람들과 대화하면서 의견을 나눴는데

Swift는 함수형도 지원하는 멀티패러다임 언어라는 관점에서 foreach는 objc의 enumarate와 다르게 고차함수이기때문에 중간에 끊기는 것이 어색한 함수이다.

그래서 stop을 제공하지 않는 것으로 이해하였다.

 

결론 : 루프에서 중간에 끊는 것이 필요하면 for-in break를 쓰자!