专栏首页韦弦的偶尔分享在SwiftUI视图中包装UIViewController

在SwiftUI视图中包装UIViewController

SwiftUI是构建应用程序的绝佳框架,但目前还远远不够完善——它有很多事情做不到,因此,如果您想添加更多高级功能,则需要学习与UIKit交流。有时,这是为了整合您为UIKit编写的现有代码(例如,如果您为拥有现有UIKit应用程序的公司工作),但有时是因为UIKit和Apple的其他框架向我们提供了我们想要展示在SwiftUI布局中的有用代码。

在此项目中,我们将要求用户从其照片库中导入图片。UIKit随附了专用的代码来执行此操作,但尚未移植到SwiftUI,因此我们需要自己编写桥接。

在编写代码之前,您需要了解三件事,所有这些都有点像UIKit 101,但是如果您仅使用SwiftUI,它们对您来说则是全新的东西。

首先,UIKit有一个名为UIView的类,它是布局中所有视图的父类。因此,标签,按钮,文本字段,滑块等等——都是视图。

其次,UIKit有一个名为UIViewController的类,该类旨在保存所有代码以使视图栩栩如生。就像UIView一样,UIViewController具有许多子类,它们可以完成各种工作。

第三,UIKit使用一种称为委托的设计模式来确定工作在哪里进行。因此,在决定我们的代码如何响应文本字段的值更改时,我们将使用我们的功能创建一个自定义类,并让我们成为文本字段的委托。

SwiftUI使我们的代码结构非常不同,不仅如此,我们主要将结构体用于视图而非类。但是,SwiftUI将UIViewUIViewController混合到单个View协议中,这使我们的代码更加简单。

无论如何,所有这些都很重要,因为UIKit要求用户从其图库中选择照片的系统使用名为UIImagePickerController的视图控制器以及名为UINavigationControllerDelegateUIImagePickerControllerDelegate的委托协议。SwiftUI无法直接使用这两个,因此我们需要对其进行包装。

我们将从简单开始,逐步发展。包装UIKit视图控制器要求我们创建一个符合UIViewControllerRepresentable协议的结构体。这是基于View的,这意味着我们定义的结构可以在SwiftUI视图层次结构体内使用,但是我们没有提供body属性,因为视图的主体是视图控制器本身——它仅显示UIKit传回的内容。

符合UIViewControllerRepresentable确实需要我们实现两种方法:一种名为makeUIViewController(),用于创建初始视图控制器,另一种名为updateUIViewController(),其设计用于在某些SwiftUI状态更改时让我们更新视图控制器。

按Cmd + N新建一个文件,选择“Swift File”,并将其命名为ImagePicker.swift。将import SwiftUI添加到新文件的顶部,然后为其提供以下代码:

struct ImagePicker: UIViewControllerRepresentable {
    typealias UIViewControllerType = UIImagePickerController
}

这还不足以正确编译代码,但是当Xcode显示错误消息“Type ImagePicker does not conform to protocol UIViewControllerRepresentable”时,请点击错误左侧的红色和白色圆圈,然后选择“fix”。这将使Xcode编写我们实际需要的两个方法,实际上,这些方法实际上足以让Swift找出视图控制器的类型,因此您可以删除typealias行。

您应该具有以下结构体:

struct ImagePicker: UIViewControllerRepresentable {
    func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
        code
    }

    func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
        code
    }
}

我们将不会使用updateUIViewController(),因此您只需删除代码(“code”)行,以使该方法为空,然后在第一个方法编写如下内容:

let picker = UIImagePickerController()
return picker

不久我们将向其中添加更多代码,但这实际上是包装基本视图控制器所需的全部。

我们的ImagePicker结构体是有效的SwiftUI视图,这意味着我们现在可以像其他任何SwiftUI视图一样在工作表中显示它。这个特定的结构体旨在显示图像,因此我们需要一个可选的Image视图来保存所选图像,以及确定该表是否在显示的某种状态。

将此替换为当前的ContentView结构体:

struct ContentView: View {
    @State private var image: Image?
    @State private var showingImagePicker = false

    var body: some View {
        VStack {
            image?
                .resizable()
                .scaledToFit()

            Button("Select Image") {
               self.showingImagePicker = true
            }
        }
        .sheet(isPresented: $showingImagePicker) {
            ImagePicker()
        }
    }
}

继续并在模拟器或真实设备上运行它。当您点击按钮时,默认的UIKit图像选择器应向上滑动,以浏览所有照片,而当您选择其中一张时,它将消失。

但是,尽管我们刚刚选择了一张图像,但在我们的视图中不会出现任何图像。您会看到,即使我们在视图中放置了SwiftUI图像,也没有将UIImagePickerController中的选择分配给它的任何地方。

为了实现这一目标,需要一个全新的概念:coordinators。

Wrapping a UIViewController in a SwiftUI view

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • SwiftUI视图的背后是什么?

    但是,这不会发生。取而代之的是,我们在屏幕中心获得了一个小的红色文本视图,并在其后出现了一片白色的海洋。

    韦弦zhy
  • 为什么SwiftUI使用 some View 作为视图类型?

    SwiftUI非常依赖于Swift的一个叫做“不透明返回类型(opaque return types)”的强大特性,您每次编写some View时都可以看到它的...

    韦弦zhy
  • SwiftUI:使用NavigationLink将新视图压入堆栈

    SwiftUI的NavigationView在视图顶部显示一个导航栏,但它还执行其他操作:它使我们可以将视图压入视图堆栈。实际上,这实际上是iOS导航的最基本形...

    韦弦zhy
  • Zookeeper体系介绍

    今天,我们将开始迈向Apache ZooKeeper的新旅程。在这个ZooKeeper教程中,我们将看到Apache ZooKeeper的含义以及ZooKeep...

    后场技术
  • 大白话带你认识 ZooKeeper !重要概念一网打尽!

    相信大家对 ZooKeeper 应该不算陌生。但是你真的了解 ZooKeeper 到底有啥用不?如果别人/面试官让你给他讲讲对于 ZooKeeper 的认识,你...

    Guide哥
  • 一文了解Zookeeper

    相信大家对 ZooKeeper 应该不算陌生。但是你真的了解 ZooKeeper 是个什么东西吗?如果别人/面试官让你给他讲讲 ZooKeeper 是个什么东西...

    用户1263954
  • Pinterest 的 ZooKeeper 经验

    Pinterest 在官方博客上发布了自己对于 ZooKeeper 的运用经验,下面一起看下 Pinterest 是如何应用 ZooKeeper 及遇到的问题和...

    dys
  • 简要分析ZooKeeper基本原理及安装部署

    Zookeeper官网地址: http://zookeeper.apache.org/

    Java后端技术
  • ZooKeeper系列教学

        本专题是ZooKeeper的一些列教学文章,本来博主打算自己写,但是写了两篇之后,查资料过程中发现了Sunddenly(⊙_⊙) 的博客,他的这个系列写...

    IT云清
  • 再不懂ZooKeeper,就安安心心把这篇文章看完

    我本人曾经使用过 ZooKeeper 作为 Dubbo 的注册中心,另外在搭建 Solr 集群的时候,我使用到了 ZooKeeper 作为 Solr 集群的管理...

    苏先生

扫码关注云+社区

领取腾讯云代金券