Lined Notebook

Swift @escaping 을 써보자

by 사슴비행기

클로저... 다들 알고 있을 것이다.

나는 이 클로저 개념이 이해가 안가고 사용법을 헤메어서 고생했던 경험이 있다.

사실 아직도 헤메기도 한다...

 

그리고 새로운 함수를 만들 때 클로저를 허용한다고 명시(@escaping)해서

함수를 호출한 후에 작업할 코드를 작성할 수 있다.

    func getVersionInfo(callBack: @escaping () -> (Void)) {
        self.versionInfo(okCallback: { (data) in
            
            self.newVersion = data["APP_VER"] as! String
            self.corection = data["CORECION_YN"] as! String
            self.appBundleId = data["APP_URL"] as! String
//                        self.newVersion = "1.0.1"  //VersionTest
            if self.currenApptVer.count == self.newVersion.count {
            } else if self.currenApptVer.count > self.newVersion.count {
                self.newVersion = self.newVersion + ".0"
            } else if self.currenApptVer.count < self.newVersion.count {
                self.currenApptVer = self.currenApptVer + ".0"
            }
            
            //최신버전
            self.lblNewVersion.text = "(최신버전 \(self.newVersion))"
            callBack()
        }) {
            callBack()
        }
    }

내가 작성한 간단한 예시이다.

이 코드는 서버에서 데이터를 받아서 현재버전과 이전버전을 저장한다.

중간에 있는 if문은 1.0.0 이렇게 세 자리인 버전과 1.0 과 같이 두 자리인 버전 값이 있기 때문에

자리수를 맞춰준 것이다. 그래야 나중에 비교하기 쉬우니까.

 

여기서 함수 매개변수를 보면 callBack: @escaping () -> (Void) 라는 부분이 있다.

그리고 그 바로 아래에도 okCallback을 매개변수로 갖는 함수를 사용한 것을 볼 수 있다.

(아주 좋은 예제다..)

 

그래서 함수를 호출했을 때 다시 callBack을 넘겨받아서 추후 작업을 할 수 있다.

getVersionInfo 함수는 callBack이 있기는 하지만 다시 넘어오는 데이터는 없다. (Void)

그런데 아래의 versionInfo를 보면 클로저로 (data) in 즉, data를 넘겨받는 걸 알 수 있다.

이렇게 데이터를 받으려면 함수를 만들 때 매개변수를

(okCallback:@escaping (넘겨받을 데이터의 자료형)->Void) 이렇게 작성하면 된다.

위의 경우는 ok가 아니라 fail 인 경우도 있어서 }) 다음에 중괄호가 한번 더 온다.

원래는 }, failedCallback: { 이렇게 시작해야 하지만

위의 예제에서는 failed 부분은 딱히 안 쓸 것 같아서 구현하지 않았다.

즉, 이렇게 생략해서 사용할 수도 있다는 것이다.

 

versionInfo 함수는 이러하다.

만약 이상한 코드가 있다면, 따로 구현해서 사용하고 있는 것이니 신경 쓰지 말고 함수 형태만 보자.

    private func versionInfo(okCallback:@escaping ([String: Any])->Void, failedCallback:@escaping ()->Void ) {
        Network.shared.versionInfo { (result) in
            switch result.status {
            case .OK:
                guard let data = result.data else {
                    failedCallback()
                    break
                }
                okCallback(data)
                break
            case .networkFailed(_):
                alert(from: self, message: "서버 연결에 실패하였습니다.\n인터넷 접속환경을 확인하세요.", okString: "확인", cancelString: "취소", okCompletion: {
                    self.versionInfo(okCallback: okCallback, failedCallback: failedCallback)
                }, cancelCompletion: {
                    
                })
                break
            default:
                failedCallback()
                break
            }
        }
    }

 

 

나도 사용하면서 감을 잡은거라 설명이 많이 부족한데... 차차 추가 수정해야겠다.

 

이렇게 callback을 받아서 사용하는 함수는 호출 이후 무조건 해야하는 일인데

비동기로 처리해도 되는 것들을 처리할 때 유용한 것 같다.

만약 특정행동을 할 때까지 다음 코드가 진행되면 안된다. 하는 경우에는 적절하지 않다.

스위프트는 기본이 비동기이기 때문에...

블로그의 정보

Beautiful Coding

사슴비행기

활동하기