[SwiftUI] UIViewRepresentable 프로토콜 사용법

 UIKit과 SwiftUI 통합하기 

 

SwiftUI 이전에는 iOS 개발을 위해 UIKit을 사용하였습니다. SwiftUI로 화면을 개발한다고 해도 UIKit을 사용할 수 밖에 없는데요. SwiftUI 화면을 UIKit에서 사용하려면 UIHostingController를 사용해서 쉽게 사용할 수 있는 것처럼 SwiftUI에서는 UIViewRepresentable이라는 프로토콜을 구현함으로써 UIView를 쉽게 SwiftUI에 반영할 수 있습니다.

 

UIViewRepresentable 프로토콜은 UIKit을 SwiftUI에서 사용하기 위해 SwiftUI 형태의 화면으로 만들기 위한 프로토콜입니다. 다음과 같이 일반 UIKit 화면을 UIViewRepresentable를 구현을 통해 SwiftUI 에서 손쉽게 사용할 수 있습니다.

struct CustomScrollView: UIViewRepresentable {
typealias UIViewType = UIScrollView
func makeUIView(context: Context) -> UIScrollView {
let scrollView = UIScrollView()
scrollView.refreshControl = UIRefreshControl()
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 50))
label.text = "Hello"
scrollView.addSubview(label)
return scrollView
}
func updateUIView(_ uiView: UIScrollView, context: Context) {
}
}
view raw blog1.swift hosted with ❤ by GitHub

 

 

 필수적으로 구현해야 하는 메서드는 다음과 같습니다. makeUIView의 경우 사용할 UIView의 화면을 반환해줍니다. updateUIView는 SwiftUI 화면을 다시 그릴 때 (예: @State 값이 업데이트 됨) 호출되는 메서드입니다.

  • makeUIView(context:) -> Self.UIViewType
  • updateUIView(Self.UIViewType, context: Self.Context)

 

 

 

이제 UIViewRepresentable를 실제 화면에 적용해보겠습니다. 단순히 일반 SwiftUI 화면을 붙이듯이 body 영역 안에 추가해주면 됩니다. 예제에서 UIRefreshControl()을 추가해주었습니다.

struct Example1: View {
var body: some View {
CustomScrollView()
}
}
struct Example1_Previews: PreviewProvider {
static var previews: some View {
Example1()
}
}
view raw blog2.swift hosted with ❤ by GitHub


 

 

 델리게이터 연결 

 

스크롤 뷰의 델리게이터를 구현해주려면 다음 메서드를 구현해주어야 합니다. target으로 self 키워드를 통해 자기 자신을 넘겨줍니다.

  • makeCoordinate() -> Coordinator
struct CustomScrollView: UIViewRepresentable {
...
func makeCoordinator() -> Coordinator {
Coordinator(target: self)
}
}
view raw blog4.swift hosted with ❤ by GitHub

 

 

 

 Cooridnator란 델리게이트를 위임해주는 역할을 합니다. 어디에 만들어도 상관 없지만 네이밍을 유지하기 위해서 CustomScrollView 화면에 추가해주겠습니다.

struct CustomScrollView: UIViewRepresentable {
...
class Coordinator: NSObject, UIScrollViewDelegate {
var target: CustomScrollView
init(target: CustomScrollView) {
self.target = target
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print("Scroll...")
}
@objc func updateRefresh(sender: UIRefreshControl) {
sender.endRefreshing()
print("Refresh")
}
}
}
view raw blog3.swift hosted with ❤ by GitHub

 

 

 

 마지막으로 makeUIView에서 context.coordinator를 통해 델리게이터를 알 수 있습니다. scrollView.delegate에 해당 객체를 연결해줍니다.

func makeUIView(context: Context) -> UIScrollView {
let scrollView = UIScrollView()
scrollView.refreshControl = UIRefreshControl()
scrollView.delegate = context.coordinator // delegate 연결
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 50))
label.text = text
scrollView.refreshControl?.addTarget(context.coordinator, action: #selector(Coordinator.updateRefresh), for: .valueChanged)
scrollView.addSubview(label)
return scrollView
}
view raw blog5.swift hosted with ❤ by GitHub

 

간단히 UIKit의 스크롤 뷰를 만들어서 화면에 추가하였습니다. 이처럼 다양한 UIKit화면을 쉽게 만들어서 델리게이터 까지 연결할 수 있습니다. 복잡한 기능을 구현하기 위해서는 다음과 같이 델리게이터 연결을 추가할 수 밖에 없는데요. 지금까지 SwiftUI와 UIKit 화면을 통합해주는 방법을 알아보았습니다.

Designed by JB FACTORY