본문 바로가기
Swfit

Closure를 사용한 UI element 생성하기

by GGShin 2022. 10. 19.

Swift 문법에서는 closure가 빠지지 않고 등장합니다. Function의 parameter로도 사용되고, return type으로도 사용이 됩니다. 그런 closure가 UI element를 생성하는데에도 사용이 될 수 있습니다. 

 

이 주제는 얼마 전 Swift 개발자로서 면접을 보았을 때 질문을 받았던 내용인데, 당시에는 이 부분에 대해 잘 알지 못해서 제대로 답변을 하지 못했습니다. 하지만 해당 사항을 물어보셨다는 것은 중요한 부분일 것이라고 생각되어 바로 알아보았습니다. 

 

먼저 closure를 이용해서 UI element를 만드는 방법은 아래 코드와 같습니다.

private let myImageView: UIImageView = { // {} 중괄호 부분이 closure입니다.

        let imageView = UIImageView() 
        //return할 UIImageView를 선언합니다. myImageView의 type과 동일해야만 return이 가능합니다!

        imageView.layer.backgroundColor = UIColor.darkGray.cgColor
        //property의 속성을 closure 내부에서 설정해 줄 수 있습니다.
        
        return imageView
        
}() //closure를 실행하여 얻게되는 값을 myImageView에 할당하는 것이므로 ()소괄호를 이용해 함수를 실행해줍니다.

 

 

Closure를 사용하지 않는다면 아래 처럼 작성이 되었을 것입니다.

 

//Initialize UIImageView
private let imageView = UIImageView() 

//layout 등 각종 설정을 별도의 function에 정의
func imageViewSetUp() {
	   imageView.layer.backgroundColor = UIColor.darkGray.cgColor
}

생김새가 많이 다르죠? 

Closure를 사용하면, property의 세부사항 설정을 위한 function을 따로 제작하지 않고 property의 할당 시에 설정을 같이 할 수 있어서 훨씬 가독성이 좋고 코드 관리가 간편합니다. 

 

하지만 이런 방식에서는 closure 내에서 다른 property에 접근(사용) 할 수가 없게 됩니다. 

왜 그럴까요? 바로 closure가 실행되는 시점이 클래스나 structure가 초기화 될 때 이고, 그 시점에는 다른 property들이 초기화되지 않은 시점이기 때문입니다. 

 

만약에 closure로 초기화하는 방식을 사용하면서도 다른 property들에 접근해야 한다면 어떻게 할까요? 해당 property를 lazy로 선언해준다면 가능합니다. lazy는 class나 structure가 초기화되는 시점이 아니라 해당 property가 사용될 때 초기화되기 때문에 가능합니다. 다른 property들이 lazy property보다 먼저 생성되어 있다는 보장이 있기 때문입니다. 

 

 private let titleLabel: UILabel = {
        let label = UILabel()
        label.backgroundColor = .darkGray
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
}()   
    
private let buttonLabel: UILabel = {
        let label = UILabel()
        label.backgroundColor = .systemPink
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
}()
    
//stackView를 lazy하게 선언했기 때문에, 다른 property를 closure 내에서 사용가능합니다.
lazy private var labelStackView: UIStackView = {
        let stack = UIStackView(arrangedSubviews: [titleLabel, buttonLabel])
        return stack
}()

 

 

예전에는 closure 방식이 그저 '깔끔하니까 사용하기 좋다' 라고만 생각했는데, 사용할 때 주의해야 할 사항들도 있다는 것을 알게되었습니다 :) 또 알게 되는 내용들이 있다면 지속적으로 추가해두겠습니다.

 

감사합니다.

 

 


참고자료

 

https://www.donnywals.com/using-closures-to-initialize-properties-in-swift/

 

Using Closures to initialize properties in Swift – Donny Wals

Closures are a powerful language feature of Swift. Learn how you can use them to assign values to your properties in this Quick Tip.

www.donnywals.com

 

https://seons-dev.tistory.com/entry/Swift-%EA%B8%B0%EC%B4%88%EB%AC%B8%EB%B2%95-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-4-%ED%81%B4%EB%A1%9C%EC%A0%80-%EC%82%AC%EC%9A%A9-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0-%EA%B8%B0%EB%B3%B8%EA%B0%92-%EB%94%94%EC%9D%B4%EB%8B%88%EC%85%94%EB%9D%BC%EC%9D%B4%EC%A0%80

 

Swift : 기초문법 [인스턴스 #4 클로저 사용 프로퍼티 기본값, 디이니셜라이저]

본 게시글은 yagom님의 Swift 프로그래밍 3판을 참고하여 작성되었습니다. 먼저 보고 와주세요! Swift : 기초문법 [인스턴스 #1 이니셜라이저, 매개변수) Swift : 기초문법 [인스턴스 #2 기본 이니셜라이

seons-dev.tistory.com

 

https://www.youtube.com/watch?v=wlrrwpWyoCI 

 

반응형