【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 SwiftUI

extension 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

K8S如何部署ActiveMQ(单机、集群)

前言 大家好,在今天的讨论中,我们将深入研究如何将ActiveMQ迁移到云端,以便更好地利用Kubernetes的容器调度和资源管理能力,确保ActiveMQ的高可用性和可扩展性。 ActiveMQ是Apache开源组织推出的一款开源的、完全支持JMS1.1和J2…

vue2:组件中extends的使用

上一篇文章中我对mixin的使用进行了一个使用和测试,这里对extend进行一个使用,其实extend和mixin还是有区别的。 上一篇文章:vue2:mixin混入的使用-CSDN博客 不过也是看实际的业务场景,我们也可以使用extend完成和mixin几乎一摸一样的操作。 不废话,上代码 创建extendTest.…

位图的详细讲解

位运算操作符:或,与,异或,按位取反。 操作符 |两个中有一个是一则为一&两个都是一则为一^相同为零,不同为一~零变成一,一变成零 什么是位运算符: 位运算是直接对整型数据的二进制进行运算。 位图概念…

告别百度网盘,搭建自己的专属网盘 ——Cloudreve,不限制下载速度!

Cloudreve 是一个用 Go 语言写的公有网盘程序,我们可以用它来快速搭建起自己的网盘服务,公有云 / 私有云都可。 顺哥博客 先来看看文档介绍吧。 支持多家云存储驱动的公有云文件系统. 演示站 • 讨论社区 • 文档 • 下载 • Telegram 群组 • 许可证 :sparkles: 特性 :cl…

webshell之Laravel和yii

EvalLoader#load 免杀效果 EvalLoader#load分析 eval命令执行函数,参数可控 MockTrait#generate 免杀效果 MockTrait#generate函数分析 存在一个eval函数 MockTrait#generate 免杀效果 view#evaluateDynamicContent 免杀效果 view#evaluateDynamicContent分析 总结…

Facebook的特点优势

Facebook作为全球最大的社交媒体平台之一,同时也是最受欢迎的社交网站之一,Facebook具有许多独特的特点和优势。本文小编将说一些关于Facebook的特点及优势。 1、全球化 Facebook拥有数十亿的全球用户,覆盖了几乎所有国家和地区。这使得人们…

初学剪辑者找视频素材就上这6个网站

视频剪辑必备的6个素材网站,高清无水印,还可以免费下载,无版权限制,赶紧收藏起来! 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYxMjky 菜鸟图库网素材非常丰富,网站主要以设计类素材为主&#…

(4)BUUCTF-web-[极客大挑战 2019]EasySQL1

前言: 觉得这个题目挺有意义的,因为最近在学数据库,但是不知道在现实中有什么应用,所以学起来也没有什么兴趣,做了这个题目,发现数据库还是挺有用处的,哈哈 知识点: mysql 中and和…

2023-11-24--oracle--实验--[Merge 语句]

oracle--实验---Merge语句 1.认知Merge 语句 • merge 语句是 sql 语句的一种。在 SQL server 、 Oracle 数据库中可用, MySQL 中不可用。 • merge 用来合并 update 和 insert 语句。目的:通过 merge 语句,根据一张表( 原数据表…

Let’s xrOS 一款让你优先体验社区创作者的 visionOS App工具

Let’s xrOS Apple Vision Pro 发布预示着空间计算时代的到来,让科技爱好者和开发者开始思考如何在新的交互、系统和硬件上打造独特的三维应用。 自 WWDC 2023 的发布会后,社交媒体上涌现了许多精美的 visionOS App 的效果图和演示视频,然而…

Windows核心编程 进程

目录 一、进程概述 二、创建进程相关API Winexec ShellExecute CreateProcess 三、进程退出相关API ExitProcess TerminateProcess GetCurrentProcess GetExitCodeProcess 四、如何理解虚拟内存空间 五、关于UAC 一、进程概述 进程:正在运行的程序 程…

set和map + multiset和multimap(使用+封装(RBTree))

set和map 前言一、使用1. set(1)、模板参数列表(2)、常见构造(3)、find和count(4)、insert和erase(5)、iterator(6)、lower_bound和upper_bound 2. multiset3. map(1)、模板参数列表(2)、构造(3)、modifiers和operations(4)、operator[] 4. multimap 二、封装RBTree迭代器原理R…

(11_23)构建高效数据流转的 ETL 系统:数据库 + Serverless 函数计算的最佳实践

作者|柳下 概述 随着企业规模和数据量的增长,数据的价值越来越受到重视。数据的变化和更新变得更加频繁和复杂,因此及时捕获和处理这些变化变得至关重要。为了满足这一需求,数据库 CDC(Change Data Capture&#xff…

晶振为什么不能放置在PCB边缘

某行车记录仪,测试的时候要加一个外接适配器,在机器上电运行测试时发现辐射超标,具体频点是84MHz、144MHz、168MHz,需要分析其辐射超标产生的原因,并给出相应的对策。辐射测试数据如下: 图1:辐…

B/S前后端分离的Java医院云HIS信息管理系统源码(LIS源码+电子病历源码)

HIS系统采用主流成熟技术开发,软件结构简洁、代码规范易阅读,SaaS应用,全浏览器访问前后端分离,多服务协同,服务可拆分,功能易扩展。多医院、多集团统一登录患者主索引建立、主数据管理,统一对外…

鸿蒙开发-ArkTS 语言-状态管理

鸿蒙开发-ArkTS 语言-基础语法 3. 状态管理 变量必须被装饰器装饰才能成为状态变量,状态变量的改变才能导致 UI 界面重新渲染 概念描述状态变量被状态装饰器装饰的变量,改变会引起UI的渲染更新。常规变量没有状态的变量,通常应用于辅助计算…

CVE-2023-22515:Atlassian Confluence权限提升漏洞复现 [附POC]

文章目录 Atlassian Confluence权限提升(CVE-2023-22515)漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 Atlassian Confluence权限提升(CVE-2023-22515)漏洞复现 [附POC] 0x01 前言 免责声明&…

Unity-类-Vector

Vector矢量 是一个基本的数学概念,它允许你描述方向和大小。在游戏和应用中,矢量通常用于描述一些基本属性,如角色的位置、物体移动的速度或两个物体之间的距离。 矢量算术是计算机编程很多方面(如图形、物理和动画)的基础,深入了解这一主题对于充分发挥 Unity 的功能很有…

从零学算法400

400.给你一个整数 n ,请你在无限的整数序列 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, …] 中找出并返回第 n 位上的数字。 示例 1: 输入:n 3 输出:3 示例 2: 输入:n 11 输出:0 解释:第…

社交媒体广告数据采集:Jsoup 的最佳实践

搜狐是中国领先的综合门户网站之一,广告在其网站上广泛投放。为了了解搜狐广告的策略和趋势,采集和分析搜狐广告数据变得至关重要。但是,搜狐网站的广告数据通常需要通过网页抓取的方式获取,这就需要一个强大的工具来解析和提取数…