원문 : Framework Intergration - Interfacing with UIKit
Interfacing with UIKit
SwiftUI는 모든 Apple 플랫폼에서 기존 UI 프레임워크와 원활하게 동작합니다. 예를 들어, SwiftUI 뷰 내부에 UIKit 뷰와 뷰 컨트롤러를 배치할수 있고 그 반대도 마찬가지입니다.
이 튜토리얼은 홈 화면에서 특정 랜드마크를 UIPageViewController와 UIPageControl를 감싼 인스턴스로 변환하는 방법을 보여줍니다. SwiftUI 뷰의 회전메뉴를 보여주기 위해 UIPageViewController을 사용할 것이고, 상태 변수와 바인딩을 사용해서 사용자 인터페이스 전체에서 데이터 업데이트를 조정합니다.
이 프로젝트를 빌드하기 위해 다음 단계를 따르거나, 완성된 프로젝트를 다운로드 받아 살펴보세요.
Section 1. UIPageViewcontroller을 표현하는 뷰 만들기(Create View to Represent a UIPageViewController)
SwiftUI에서 UIKit 뷰와 뷰 컨트롤러를 표현하기 위해서, UIViewRepresentable과 UIViewControllerRepresentable 프로토콜을 준수하는 타입을 만듭니다. 여러분의 사용자정의 타입은 표현하고자 하는 UIKit 타입을 만들고 구성하며, SwiftUI는 생명주기를 관리하고 필요할때 업데이트합니다.
1 단계
PageViewController.swift라는 이름을 가진 SwiftUI 뷰 파일을 만들고, UIViewControllerRepresentable을 준수하는 PageViewcontroller 타입을 선언합니다.
페이지 뷰 컨트롤러는 UIViewController 인스턴스의 배열을 저장합니다. 그것들은 랜드마크 간에 스크롤하는 페이지들입니다.
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
}
다음으로, UIViewControllerRepresentable 프로토콜에 대한 2개의 요구사항을 추가합니다.
2 단계
원하는 구성으로 UIPageViewController을 만드는 makeUIViewController(context:) 메소드를 추가합니다.
SwiftUI는 뷰가 보여질 준비가 되었을때, 이 메소드를 한번 호출하고, 그리고나서 뷰 컨트롤러의 생명주기를 관리합니다.
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
return pageViewController
}
}
3 단계
배열의 첫번째 뷰 컨트롤러를 표현하기 위해, updateUIViewController(_:context:) 메소드에 setViewControllers(_:direction:animated:)를 호출을 추가합니다.
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[controllers[0]], direction: .forward, animated: true)
}
}
다른 SwiftUI 뷰를 만들어서 UIViewControllerRepresetable뷰를 표현합니다.
4 단계
PageView.swift 이름의 새로운 SwiftUI 뷰 파일을 만들고, PageViewController를 자식 뷰처럼 선언하기 위해 PageView 타입을 업데이트합니다.
일반적인 초기화가 뷰의 배열을 가지고 오는 것을 주의하고, 각 항목을 UIHostingController로 만듭니다. UIHostingController는 UIKit 문맥상에 SwiftUI 뷰을 나타내는 UIViewController의 하위클래스 입니다.
import SwiftUI
struct PageView<Page: View>: View {
var viewControllers: [UIHostingController<Page>]
init(_ views: [Page]) {
self.viewControllers = views.map { UIHostingController(rootView: $0) }
}
var body: some View {
PageViewController(controllers: viewControllers)
}
}
struct PageView_Preview: PreviewProvider {
static var previews: some View {
PageView()
}
}
5 단계
미리보기 공급자를 업데이트해서 필요한 뷰의 배열을 전달하고, 미리보기를 시작합니다.
import SwiftUI
struct PageView<Page: View>: View {
var viewControllers: [UIHostingController<Page>]
init(_ views: [Page]) {
self.viewControllers = views.map { UIHostingController(rootView: $0) }
}
var body: some View {
PageViewController(controllers: viewControllers)
}
}
struct PageView_Preview: PreviewProvider {
static var previews: some View {
PageView(features.map { FeatureCard(landmark: $0) })
.aspectRatio(3/2, contentMode: .fit)
}
}
6 단계
계속하기 전에 캔버스에 PageView 미리보기를 고정합니다. - 이 뷰는 어디에서든 동작합니다.
Section 2. 뷰 컨트롤러의 데이터 소스 만들기(Create the View Controller’s Data Source)
짧은 몇 단계에서, 여러분은 많은 것을 했습니다 - PageViewController는 UIPageViewController을 사용해서 SwiftUI 뷰에서 SwiftUI 컨텐츠를 보여줍니다. 이제 페이지에서 페이지로 스와이핑으로 이동이 가능해야 합니다.
UIKit 뷰 컨트롤러를 표현하는 SwiftUI 뷰는 SwiftUI 관리하는 Coordinator 타입을 정의할수 있고 표현가능한(representable) 뷰의 컨텍스트의 일부로 제공됩니다.
1 단계
PageViewController에서 중첩된 Coordinator 클래스를 선언합니다.
SwiftUI는 UIViewControllerRepresentable 타입의 조정자(coordinator)를 관리하고 위에서 만들었던 메소드를 호출할때 컨텍스트의 일부로 제공합니다.
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[controllers[0]], direction: .forward, animated: true)
}
class Coordinator: NSObject {
var parent: PageViewController
init(_ pageViewController: PageViewController) {
self.parent = pageViewController
}
}
}
2 단계
coordinator를 만들기 위해 PageViewController에 다른 메소드를 추가합니다.
SwiftUI는 makeUIViewController(context:) 전에 makeCoordinator() 메소드를 호출하며, 뷰 컨트롤러를 구성할때 coordinator 객체를 사용합니다.
팁
coordinator를 사용해서 델리게이터, 데이터소스, 대상-동작으로 사용자 이벤트 응답 등 일반적인 Cocoa 패턴을 구현할 수 있습니다.
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[controllers[0]], direction: .forward, animated: true)
}
class Coordinator: NSObject {
var parent: PageViewController
init(_ pageViewController: PageViewController) {
self.parent = pageViewController
}
}
}
3 단계
Coordinator 타입에 UIPageViewControllerDataSource를 준수하도록 추가하고 두개의 필수 메소드를 구현합니다.
이 두 메소드들은 뷰 컨트롤러들 간의 관계를 형성하며, 그것들 사이를 스와이프로 왔다갔다 할 수 있습니다.
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[controllers[0]], direction: .forward, animated: true)
}
class Coordinator: NSObject, UIPageViewControllerDataSource {
var parent: PageViewController
init(_ pageViewController: PageViewController) {
self.parent = pageViewController
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index == 0 {
return parent.controllers.last
}
return parent.controllers[index - 1]
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index + 1 == parent.controllers.count {
return parent.controllers.first
}
return parent.controllers[index + 1]
}
}
}
4 단계
coordinator를 UIPageViewController의 데이터 소스로 추가합니다.
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
pageViewController.dataSource = context.coordinator
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[controllers[0]], direction: .forward, animated: true)
}
class Coordinator: NSObject, UIPageViewControllerDataSource {
var parent: PageViewController
init(_ pageViewController: PageViewController) {
self.parent = pageViewController
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index == 0 {
return parent.controllers.last
}
return parent.controllers[index - 1]
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index + 1 == parent.controllers.count {
return parent.controllers.first
}
return parent.controllers[index + 1]
}
}
}
5 단계
라이브 미리보기를 켜고 스와이프(swip) 동작을 테스트합니다.
https://docs-assets.developer.apple.com/published/2fa551fd64/_p42_swipe_interactions.mp4
Section 3. SwiftUI 뷰의 상태에서 페이지 추적하기(Track the Page in a SwiftUI View’s State)
사용자정의 UIPageControl을 추가를 준비하기 위해, PageView내의 현재 페이지를 추적하는 방법이 필요합니다.
이를 위해서, PageView에 @State 속성을 추가할 것이고, 이 속성에 대한 바인딩을 PageViewController 뷰로 전달합니다. PageViewController는 보이는 페이지와 일치하도록 바인딩을 업데이트 합니다.
1 단계
PageViewController의 속성처럼 currentPage 바인딩을 추가해서 시작합니다.
@Binding 속성을 선언 하는 것 외에, setViewControllers(_:direction:animated:) 호출을 업데이트 하며, currentPage 바인딩의 값을 전달합니다.
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
@Binding var currentPage: Int
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
pageViewController.dataSource = context.coordinator
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[controllers[currentPage]], direction: .forward, animated: true)
}
class Coordinator: NSObject, UIPageViewControllerDataSource {
var parent: PageViewController
init(_ pageViewController: PageViewController) {
self.parent = pageViewController
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index == 0 {
return parent.controllers.last
}
return parent.controllers[index - 1]
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index + 1 == parent.controllers.count {
return parent.controllers.first
}
return parent.controllers[index + 1]
}
}
}
2 단계
PageView에 @State 변수를 선언하고 자식 PageViewController를 만들때 그 속성에 바인딩을 전달합니다.
중요
상태들 저장하는 값에 대한 바인딩을 만들기 위해 $ 구문을 사용하는 것을 기억하세요.
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
@Binding var currentPage: Int
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
pageViewController.dataSource = context.coordinator
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[controllers[currentPage]], direction: .forward, animated: true)
}
class Coordinator: NSObject, UIPageViewControllerDataSource {
var parent: PageViewController
init(_ pageViewController: PageViewController) {
self.parent = pageViewController
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index == 0 {
return parent.controllers.last
}
return parent.controllers[index - 1]
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index + 1 == parent.controllers.count {
return parent.controllers.first
}
return parent.controllers[index + 1]
}
}
}
3 단계
초기값을 변경해서 PageViewController에 바인딩을 처리되는지 테스트합니다.
실험
페이지 뷰 컨트롤러를 두번째 뷰로 이동하는 PageView에 버튼을 추가합니다.
import SwiftUI
struct PageView<Page: View>: View {
var viewControllers: [UIHostingController<Page>]
@State var currentPage = 1
init(_ views: [Page]) {
self.viewControllers = views.map { UIHostingController(rootView: $0) }
}
var body: some View {
PageViewController(controllers: viewControllers, currentPage: $currentPage)
}
}
struct PageView_Preview: PreviewProvider {
static var previews: some View {
PageView(features.map { FeatureCard(landmark: $0) })
.aspectRatio(3/2, contentMode: .fit)
}
}
4 단계
currentPage 속성이 있는 텍스트뷰를 추가하며, @State 속성의 값을 계속 볼 수 있습니다.
페이지간에 스와이프할때 그 옵져버는 값을 변경하지 않습니다.
import SwiftUI
struct PageView<Page: View>: View {
var viewControllers: [UIHostingController<Page>]
@State var currentPage = 0
init(_ views: [Page]) {
self.viewControllers = views.map { UIHostingController(rootView: $0) }
}
var body: some View {
VStack {
PageViewController(controllers: viewControllers, currentPage: $currentPage)
Text("Current Page: \(currentPage)")
}
}
}
struct PageView_Preview: PreviewProvider {
static var previews: some View {
PageView(features.map { FeatureCard(landmark: $0) })
}
}
5 단계
PageViewController.swift에서, coordinator가 UIPageControllerDelegate를 준수하고, pageViewController(_:didFinishAnimating:previousViewControllers:transitionCompleted completed: Bool)메소드를 추가합니다.
SwiftUI는 페이지 교체 애니메이션이 완료될때, 이 메소드를 호출하기 때문에, 현재 뷰 컨트롤러의 인덱스를 찾을 수 있고 바인딩을 업데이트 할 수 있습니다.
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
@Binding var currentPage: Int
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
pageViewController.dataSource = context.coordinator
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[controllers[currentPage]], direction: .forward, animated: true)
}
class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var parent: PageViewController
init(_ pageViewController: PageViewController) {
self.parent = pageViewController
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index == 0 {
return parent.controllers.last
}
return parent.controllers[index - 1]
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index + 1 == parent.controllers.count {
return parent.controllers.first
}
return parent.controllers[index + 1]
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed,
let visibleViewController = pageViewController.viewControllers?.first,
let index = parent.controllers.firstIndex(of: visibleViewController)
{
parent.currentPage = index
}
}
}
}
6 단계
데이터 소스외에도, UIPageViewController에 대한 델리게이터에 coordinator를 지정합니다.
바인딩으로 양방향을 연결되면, 스와이프 한 후에, 텍스트 뷰는 현재 페이지 숫자를 보여주기 위해 업데이트 합니다.
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
@Binding var currentPage: Int
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
pageViewController.dataSource = context.coordinator
pageViewController.delegate = context.coordinator
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[controllers[currentPage]], direction: .forward, animated: true)
}
class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var parent: PageViewController
init(_ pageViewController: PageViewController) {
self.parent = pageViewController
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index == 0 {
return parent.controllers.last
}
return parent.controllers[index - 1]
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index + 1 == parent.controllers.count {
return parent.controllers.first
}
return parent.controllers[index + 1]
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed,
let visibleViewController = pageViewController.viewControllers?.first,
let index = parent.controllers.firstIndex(of: visibleViewController)
{
parent.currentPage = index
}
}
}
}
Section 4. 사용자정의 페이지 컨트롤 추가하기(Add Custom Page Control)
여러분의 뷰에 SwiftUI UIViewRepresentable 뷰로 감싸진 사용자정의 UIPageControl을 추가할 준비가 되었습니다.
1 단계
PageControl.swift 라는 새로운 SwiftUI 뷰 파일을 만듭니다. PageControl 타입을 UIViewRepresentable 프로토콜을 준수하도록 합니다.
UIViewRepresentable과 UIViewControllerRepresentable 타입은 기본 UIKit 타입에 해당하는 메소드들을 사용하며, 동일한 생명주기를 가지고 있습니다.
import SwiftUI
import UIKit
struct PageControl: UIViewRepresentable {
var numberOfPages: Int
@Binding var currentPage: Int
func makeUIView(context: Context) -> UIPageControl {
let control = UIPageControl()
control.numberOfPages = numberOfPages
return control
}
func updateUIView(_ uiView: UIPageControl, context: Context) {
uiView.currentPage = currentPage
}
}
2 단계
페이지 컨트롤로 텍스트 박스를 교체하고, 레이아웃을 VStack을 ZStack로 교체합니다.
페이지 수를 전달하고 현재 페이지를 바인딩하기 때문에, 페이지 컨트롤은 이미 정확한 값을 보여주고 있습니다.
import SwiftUI
struct PageView<Page: View>: View {
var viewControllers: [UIHostingController<Page>]
@State var currentPage = 0
init(_ views: [Page]) {
self.viewControllers = views.map { UIHostingController(rootView: $0) }
}
var body: some View {
ZStack(alignment: .bottomTrailing) {
PageViewController(controllers: viewControllers, currentPage: $currentPage)
PageControl(numberOfPages: viewControllers.count, currentPage: $currentPage)
.padding(.trailing)
}
}
}
struct PageView_Preview: PreviewProvider {
static var previews: some View {
PageView(features.map { FeatureCard(landmark: $0) })
}
}
다음으로, 사용자가 페이지간에 이동할 수 있도록 페이지가 상호작용하는 페이지 컨트롤을 만듭니다.
3 단계
PageControl에서 중첩된 Coordinator 타입을 만들고 새로운 coordinator를 만들고 반환하기 위해makeCoordinator()` 메소드를 추가합니다.
UIPageControl같은 UIControl 하위클래스는 델리게이터(delegation) 대신에 대상-동작(target-action)을 사용하기 때문에, Coordinator는 현재 페이지 바인딩을 업데이트 하기 위해 @objc 메소드를 구현합니다.
import SwiftUI
import UIKit
struct PageControl: UIViewRepresentable {
var numberOfPages: Int
@Binding var currentPage: Int
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UIPageControl {
let control = UIPageControl()
control.numberOfPages = numberOfPages
return control
}
func updateUIView(_ uiView: UIPageControl, context: Context) {
uiView.currentPage = currentPage
}
class Coordinator: NSObject {
var control: PageControl
init(_ control: PageControl) {
self.control = control
}
@objc func updateCurrentPage(sender: UIPageControl) {
control.currentPage = sender.currentPage
}
}
}
4 단계
valueChanged 이벤트에 대한 대상에 coordinator를 추가하며, 수행 동작으로updateCurrentPage(sender:)` 메소드를 지정합니다.
import SwiftUI
import UIKit
struct PageControl: UIViewRepresentable {
var numberOfPages: Int
@Binding var currentPage: Int
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UIPageControl {
let control = UIPageControl()
control.numberOfPages = numberOfPages
control.addTarget(
context.coordinator,
action: #selector(Coordinator.updateCurrentPage(sender:)),
for: .valueChanged)
return control
}
func updateUIView(_ uiView: UIPageControl, context: Context) {
uiView.currentPage = currentPage
}
class Coordinator: NSObject {
var control: PageControl
init(_ control: PageControl) {
self.control = control
}
@objc func updateCurrentPage(sender: UIPageControl) {
control.currentPage = sender.currentPage
}
}
}
5 단계
이제 모든 다른 상호작용을 시도해보세요 - PageView는 UIKit과 SwiftUI 뷰와 컨트롤러가 함께 동작할 수 있습니다.
https://docs-assets.developer.apple.com/published/46374ee39b/_p42_all_interactions.mp4
이해하는지 확인하기(Check Your Understanding)
퀴즈 1. 어떤 프로토콜이 UIKit 뷰 컨트롤러를 SwiftUI로 연결하는데 사용하나요?
- UIViewRepresentable
- UIHostingController
- UIViewControllerRepresentable
[정답 : 3]
UIViewControllerRepresentable를 준수하는 구조체를 만들고 SwiftUI 뷰 계층구조에 UIViewController를 포함하도록 프로토콜 요구사항을 구현합니다.
퀴즈 2. 어떤 메소드로 UIViewControllerRepresentable 타입에 대한 델리게이터나 데이터 소스를 만드나요?
- 델리게이터나 데이터 소스를 사용하기 때문에, 동일한 makeUIViewController(context:) 메소드에서 UIVeiwController를 만듭니다.
- UIViewControllerRepresentable 타입에 대한 초기화에서
- makeCoordinator() 메소드에서
[정답 : 3]
makeCoordinator()에서 coordinator 타입 인스턴스를 반환합니다. SwiftUI는 생명주기를 관리하고 다른 필수 메소드에서 Context 매개변수의 일부로 제공합니다.
'SwiftUI > Tutorials' 카테고리의 다른 글
Working with UI Controls (0) | 2019.08.13 |
---|---|
Composing Complex Interfaces (0) | 2019.08.13 |
Animating Views and Transitions (0) | 2019.08.13 |
Drawing Paths and Shapes (0) | 2019.08.13 |
Handling User Input (0) | 2019.08.13 |
Building Lists and Navigation (0) | 2019.07.23 |
Creating and Combining Views (0) | 2019.07.23 |