티스토리 뷰

Escaping Closure (탈출 클로저)

class ViewController: UIViewController {

	var sampleClosure : () -> Void = {}
    
    override func viewDidLoad() {
    	super.viewDidLoad()
        
        callback {
        	print("Closure가 실행되었습니다.")
            
        }
    }
    
    func callback(closure: () -> Void) {
    	sampleClosure = closure
        sampleClosure()
        
    }
    
}

클래스에 sampleClosure 변수를 선언하고, 해당 callBack 함수 내부에서 매개변수로 받은 closure를 대입하려고 하면 에러가 발생!

스위프트에서는 함수의 파라미터로 전달된 클로저는 기본적으로 함수 내부에서만 사용 가능! (탈출불가 상태)

 

파라미터로 받은 클로저는 직접 실행만 가능하고, 외부 변수나 상수에 대입도 불가능한 형태이다.

원래는 클로저가 파라미터로 넘어가게 되면 반드시! 해당 함수가 끝나서 리턴되기 전에, 해당 클로저는 실행이 된다.

 

즉, 해당 함수가 끝나게 되면 파라미터로 넘어간 클로저는 사용이 불가능해진다.

 

func callback(closure: @escaping() -> Void) {
    	sampleClosure = closure
        sampleClosure()
    }

매개변수로 넘어온 클로저 앞에서 @escaping을 달아주면, 아까 발생하던 오류가 사라진다.

 

이렇게 클로저를 탈출 가능하게 만들면 가능한 것은 크게 2가지이다.

  • 해당 클로저를 외부 변수/상수에 저장 가능
  • 해당 함수가 끝나서 리턴 이후에 해당 클로저 실행이 가능

탈출 클로저를 만들게 되면 함수의 실행 순서를 정할 수 있다.

함수 내부에서만 호출이 가능한게 아니라, "탈출" 했기 때문에, 외부에서도 사용이 가능한 형태!

func SetImage(url: String) -> UIImgae {
	var result = UIImage()
   
   // 이미지를 서버에서 받아오는 부분
    Alamofire.request(url).responseImage { (response) in 
    	if let image = response.result.value {
        	result = image
        }
    }
    return result
}

위 코드는 이미지를 서버에서 받아오는 코드이다.

 

비동기 방식으로 처리하면 코드의 실행 완료를 기다리지 않고 진행함과 동시에 다음 라인으로 진행한다.

통신하는 부분에서는 코드들이 비동기적으로 실행된다.

따라서, return result가 실행되기 전에 이미지를 서버에서 받아오는 부분이 안끝나면 빈 이미지가 return 된다.

-> 서버에서 받아오는 부분이 끝나고, 정상적인 이미지가 넘어와야 한다!

 

return result 에 빈 이미지가 있을지? 정상적인 이미지가 있을지? 모른다는 얘기!

 

@escaping closure 를 사용하면, 함수의 실행 순서를 결정 할 수 있다.

이 점을 활용해서, 서버에서 데이터를 받아오는 작업이 끝났을 때 탈출 클로저 호출!

방식으로 사용하게 된다면 안전하게 데이터를 가져올 수 있다.

 

탈출 클로저를 사용 안 했을 경우

함수 리턴되기 전에 서버 작업 완료되었는지 보장이 안됨

-> 데이터를 다루는데에 문제가 발생 (데이터 받기도 전에 함수가 종료된다면 클로저 실행 불가)

 

탈출 클로저 사용한 경우

함수가 리턴되더라도 서버 작업 완료될 때 전달 받는 것이 가능

-> 데이터를 안전하게 받는 것이 보장!

 

Singleton Pattern (싱글턴 패턴)

특정 용도로 객체 하나만 생성하여, 공용으로 사용하고 싶을 때 사용하는 디자인 유형

class UserInfo {
	var id: String?
    var password: String?
    var name: String?
}

다음과 같이 유저의 정보를 저장하는 클래스가 하나 있다.

 

뷰컨마다 이름을 따로 받는다면 각각의 인스턴스에서 정보가 따로 존재하게 된다.

인스턴스는 참조 타입이기에, 인스턴스 하나 생성해서 A->B->C 로 넘겨주는 방식이 있지만 굉장히 번거로운 방법이다.

 

그러면, 해당 인스턴스는 최초 생성될 때 전역으로 저장해두고, 그 이후에는 이 전역 인스턴스에서만 접근하게 하자! 라는 방법을 사용!

class UserInfo {
	static let shard = UserInfo()
    
	var id: String?
    var password: String?
    var name: String?
}

static을 이용해 인스턴스를 전역으로 저장할 프로퍼티를 생성!

//A ViewController

let userInfo = UserInfo.shared
userInfo.id = "seungchan"

위에서 static 으로 선언해두었던 인스턴스를 통해 동일한 인스턴스에 접근 할 수 있게 된다.

 

'Sopt 28th 세미나 - iOS' 카테고리의 다른 글

[Swift] Alamofire (GET) 요약  (0) 2021.08.20
[Swift] Alamofire (GET) & Postman  (0) 2021.08.20
[Swift] Encode / Decode  (0) 2021.08.19
[Swift] Animation  (0) 2021.08.16
[Swift] Refresh Control (당겨서 새로고침)  (0) 2021.08.16
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
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
글 보관함