【SwiftUI】7.预览及其内部机制

上一篇讲到了组件及组件化,从概念和优/缺点两个方向说明了组件化的意义,更为重要的是,组件和组件化是一个在编程领域,放之四海皆可以的概念,理解和运用它是非常必要的,希望大家能掌握。今天我们介绍另一个特性--预览(Preview).

概念

预览是苹果给SwiftUI新添加的一个重要特性,也可以算得上是一个重大突破。它可以直接在macOS上进行渲染并显示界面(即所见即所得),很类似Flutter的Hot Reloading。熟悉Hot Reloading技术的同学都知道,它给我们编程带来很多的方便。

然而,相比Hot Reloading技术,预览又有些不同,甚至可以说更好一些。因为Hot Reloading技术需要运行App,并且当调整界面或数据状态发生变化的时,需要重启App。而预览就完全不需要做这些事情(不用运行App;数据变化也不需要重启App)。

再说明一点,预览的实现机制整体概括为:Xcode工具对代码进行静态分析(依赖于SwiftSyntax框架),然后找到所有遵循ProviewProvider协议的类型,进而对此进行渲染和显示。

讲完了概念,用示例图来展示预览情况。

现象

上图表示:

1.左边是编写代码区域,右边是实时预览区域,实现了所见即所得的效果。

2.红框标注了遵循ProviewProvider协议。

介绍完了预览的概念和样式。大家一定很好奇预览功能是怎么实现的?它的内部机制是怎么样的呢?下面我们一起看下。

内部机制

我们先拿个工程来举例。先创建一个SwiftUI的新工程(注意:先不要写任何代码,也不启动预览功能)。如下图所示

然后找到DerivedData目录。找一个后缀.preview-thunk.swift的文件

此时,在这个目录上是找不到的(因为没有编译,连工程目录都没有)。

接着编译(Command+B)工程(记得开启预览功能).就可以在DerivedData目录上找到 .preview-thunk.swift文件了。对于本机来说,.preview-thunk.swift的完整路径为:

DerivedData/工程目录/Build/Intermediates.noindex/Previews/TestSwiftUIDemo5/Intermediates.noindex/TestSwiftUIDemo5.build/Debug-iphonesimulator/TestSwiftUIDemo5.build/Objects-normal/x86_64/ContentView.5.preview-thunk.swift.

文件效果如下图所示

然后打开该文件。会显示如下代码

@_private(sourceFile: "ContentView.swift") import TestSwiftUIDemo5
import SwiftUI
import SwiftUIextension ContentView_Previews {@_dynamicReplacement(for: previews) private static var __preview__previews: some View {#sourceLocation(file: "/Users/hyh/Documents/MyProject/TestSwiftUIDemo5/TestSwiftUIDemo5/ContentView.swift", line: 19)__designTimeSelection(ContentView(), "#5016.[2].[0].property.[0].[0]")#sourceLocation()}
}extension ContentView {@_dynamicReplacement(for: body) private var __preview__body: some View {#sourceLocation(file: "/Users/hyh/Documents/MyProject/TestSwiftUIDemo5/TestSwiftUIDemo5/ContentView.swift", line: 12)__designTimeSelection(Text(__designTimeString("#5016.[1].[0].property.[0].[0].arg[0].value", fallback: "Hello, world!")).padding(), "#5016.[1].[0].property.[0].[0]")#sourceLocation()}
}import struct TestSwiftUIDemo5.ContentView
import struct TestSwiftUIDemo5.ContentView_Previews

这个代码不用看懂,我们只需要了解下面几个特性:

  • @_private(sourceFile: ): 让当前代码可以访问原本外部无法访问的变量和函数,这样我们就无需在项目代码中提高访问权限。简单来说,通过该函数能直接访问一些不能访问的变量或函数。

  • #sourceLocation(file: ,line: ):负责将衍生代码中发生的崩溃等调试信息反映在我们写的代码上,帮助开发者找到对应的源代码位置。等同于错误日志输入。

  • @_dynamicReplacement(for: ):指定某个方法作为另一个方法的动态替代方法。在上面的代码中,主要是__preview__previews 函数并让它作为预览入口。

  • 最后两行import代码,是导入struct TestSwiftUIDemo5.ContentView和

    struct TestSwiftUIDemo5.ContentView_Previews 两个结构体的相关信息(包含变量),保证代码的编译成功。

以上代码,简单来说,就是确定一个入口函数,并且依赖上自己编写的代码的相关信息。

这里注意下

在该目录下有两个.preview-thunk.swift文件,经过实践验证:这两个文件内容基本一样,一起变化(代码一变化,两文件内容一起变化),所以存在两个一样的文件。

然而,Xcode如何加载预览视图的呢?

这个就需要查看ContentView.5.preview-thunk.dylib(.dylib后缀是动态库)。如下图所示

然后打开.dylib文件,需要在在当前目录下,在终端执行

nm ./ContentView.5.preview-thunk.dylib | grep ' T '//该命令作用是罗列出.dylib文件中的符号

执行结果如下图

其实,该动态库只有一个_main 方法。在该方法中,主要进行了定义预览相关的环境设置、设置预览初始状态等操作。然后,再创建了用于预览的进程。并通过 XPC 在预览进程与 Xcode 之间进行通信,最后实现了在 Xcode 中预览特定视图的目的。这就是Xcode加载预览视图的整个过程。

最后总结下预览的工作流程。

预览的工作流程(该流程描述来自网络)

  • Xcode 生成预览衍生代码文件

  • Xcode 编译整个项目,解析文件、获取预览视图实现、准备依赖的其他资源

  • Xcode 编译预览衍生代码文件,创建动态库

  • Xcode 启动预览线程,在其中加载 _XCPreviewKit 框架和预览衍生文件生成的 dylib

  • XCPreviewKit 框架在预览线程中创建预览窗口

  • Xcode 通过 XPC 发送消息指令, _XCPreviewKit 框架更新预览窗口,并在两个线程建进行交互与同步

  • 用户在 Xcode 界面中看到预览效果

以上就是预览的概念和内部机制的介绍。

参考

https://zhuanlan.zhihu.com/p/631420119

https://www.guardsquare.com/blog/behind-swiftui-previews

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/214944.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git的使用:本地git下载、sshkey的添加、github仓库创建及文件上传

一、github创建账号 即github注册账号,登录github官网,根据提示注册即可 github官网 二、git客户端下载安装 已有很多git下载安装的博文了,在此就不赘述 三、sshkey的生成与添加 1、sshkey的生成以及查看 // sshkey的生成命令&#xff…

ThinkPHP6.1 多应用模式的一些事儿

TP安装就不说了,直接从安装完成开始了。 安装多应用模式扩展 think-multi-app composer require topthink/think-multi-app删除 app 目录下的 controller 文件夹(TP 是根据是否有这个文件夹来判断单应用模式还是多应用模式的)。 创建应用 …

vue中下载文件后无法打开的坑

今天在项目开发的时候临时要添加个导出功能我就写了一份请求加导出得代码, 代码: //导出按钮放开exportDutySummarizing (dataRangeInfo) {const params {departmentName: dataRangeInfo.name,departmentQode: dataRangeInfo.qode}//拼接所需得urlcons…

数据结构算法-贪心算法

引言 贪心:人只要有 “需求“ ,都会有有点“贪“, 这种“贪“是一种选择,或者“”取舍“ RTS(即时战略)游戏: 帝国时代里 首先确保拥有足够的人口 足够的粮食,足够的战略资源 足够的…

Unity RenderFeature架构分析

自定义RenderFeature接口流程 URP内部ScriptableRenderPass分析 public、protected属性 renderPassEvent :渲染事件发生的时刻colorAttachments :渲染的颜色纹理列表 m_ColorAttachmentscolorAttachment :m_ColorAttachments[0];depthAttac…

希宝猫罐头怎么样?专业人士告诉你什么牌子的猫罐头好

而作为一个开猫咖5年的老板,对于猫咪吃的健康我一直很重视,毕竟健康的猫咪是决定我店铺生意红火的重要原因。我有必要给大家分享一下这些年我喂养猫罐头的经验,并推荐我觉得可以的猫罐头。那么希宝猫罐头表现怎么样呢? 希宝猫罐头…

Python开源项目之人工智能老照片修复算法学习

文章目录 前言项目环境搭建conda虚拟环境创建激活环境Pytorch安装Synchronized-BatchNorm-PyTorch repository安装Global目录Synchronized-BatchNorm-PyTorch项目部署检测预处理模型下载下载脸部增强模型文件下载依赖完整部署后项目结构 项目使用验证一下总结关于Python技术储备…

Android Tombstone 与Debuggerd 原理浅谈

一、前言 Android系统类问题主要有stability、performance、power、security。Android集成一个守护进程tombstoned是android平台的一个守护进程,它注册成3个socket服务端,客户端封装在crash_dump和debuggerd_client。 crash_dump用于跟踪定位C crash&am…

万宾科技可燃气体监测仪的功能有哪些?

随着城市人口的持续增长和智慧城市不断发展,燃气作为一种重要的能源供应方式,已经广泛地应用于居民生活和工业生产的各个领域。然而燃气泄漏和安全事故的风险也随之增加,对城市的安全和社会的稳定构成了潜在的威胁。我国燃气管道安全事故的频…

mac 修改 hosts 文件

打开 hosts 所在文件夹 command shift G 快捷键 输入:“/private/etc/hosts” 后回车 如下所示 进入 hosts 文件所在位置,找到 hosts 文件,双击打开 修改 hosts 文件 将所需要的配置信息追加到hosts 文件中,或者修改需要改…

智慧楼宇可视化视频综合管理系统,助力楼宇高效安全运行

随着互联网技术的进步和发展,智能化的楼宇建设也逐步成为人们选择办公场所是否方便的一个重要衡量因素。在智能化楼宇中,安全管理也是重要的一个模块。得益于互联网新兴技术的进步,安防视频监控技术也得到了快速发展并应用在楼宇的安全管理中…

burp抓取雷电模拟器的数据包

文章目录 一、从burp中导出证书二、雷电模拟器的相关设置三、将burp的证书添加到模拟器的系统证书下四、安装ProxyDroid 所需软件 雷电模拟器版本:4.0.83Burp Suite Community Edition v2023.10.3.6ProxyDroid 起因:常规方法(wifi处添加代理…