当前位置: 首页 > news >正文

SwiftUI八与UIKIT交互

代码下载

SwiftUI可以在苹果全平台上无缝兼容现有的UI框架。例如,可以在SwiftUI视图中嵌入UIKit视图或UIKit视图控制器,反过来在UIKit视图或UIKit视图控制器中也可以嵌入SwiftUI视图。

本文展示如何把landmark应用的主页混合使用UIPageViewController和UIPageControl。使用UIPageViewController来展示由SwiftUI视图构成的轮播图,使用状态变量和绑定来操作用户界面数据的更新。

下载起步项目并跟着本篇教程一步步实践,或者查看本篇完成状态时的工程代码去学习,项目文件。

创建一个用来展示UIPageViewController的SwiftUI视图

为了在SwiftUI视图中展示UIKit视图和UIKit视图控制器,需要创建遵循 UIViewRepresentable 和 UIViewControllerRepresentable 协议的类型。创建的自定义视图类型,用来创建和配置所要展示的UIKit类型,SwiftUI框架来管理UIKIt类型的生命周期并在适当的时机更新它们。
请添加图片描述

1、创建一个新的 SwiftUI 视图文件,命名为 PageViewController.swift,并且声明 PageViewController 类型遵循 UIViewControllerRepresentable 协议。这个页面视图控制器存放一个 UIViewController 实例数组,数组中的每一个元素代表在地标滚动过程中的一页视图。

import SwiftUI
import UIKitstruct PageViewController<Page: View>: UIViewControllerRepresentable {var pages: [Page]}

下一步添加UIViewControllerRepresentable协议的两个实现, 目前因为协议方法没有完成实现,会有报错提示。

2、添加一个 makeUIViewController(context:) 方法,方法内部以指定的配置创建一个 UIPageViewController。SwiftUI 会在准备显示视图时调用一次 makeUIViewController(context:) 方法创建 UIViewController 实例,并管理它的生命周期。

    func makeUIViewController(context: Context) -> UIPageViewController {let pageViewController = UIPageViewController(transitionStyle: .scroll,navigationOrientation: .horizontal)return pageViewController}

3、添加 updateUIViewController(_:context:) 方法,这个方法里调用 setViewControllers(_:direction:animated:) 方法展示数组中的第一个视图控制器。

    func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {pageViewController.setViewControllers([UIHostingController(rootView: pages[0])], direction: .forward, animated: true)}

现在,创建了 UIHostingController,它在每次更新时托管页面SwiftUI视图。稍后将通过在页面视图控制器的生命周期中只初始化一次控制器来提高效率。

4、将下载的项目文件 Resources 目录中的图片拖到应用程序的 Asset 目录中。地标的特征图像,如果存在的话,其维度与常规图像不同。

5、将计算属性添加到返回特征图像(如果存在)的 Landmark 结构中。

   var featureImage: Image? {isFeatured ? Image(imageName + "_feature") : nil}

6、添加一个新的 SwiftUI 视图文件,名为 FeatureCard.swift,用于显示地标的特征图像。

import SwiftUIstruct FeatureCard: View {var landmark: Landmarkvar body: some View {landmark.featureImage?.resizable()}
}#Preview {FeatureCard(landmark: ModelData().features[0]).aspectRatio(3 / 2, contentMode: .fit)
}

包括长宽比修改器,这样它就可以模仿视图的长宽比,而 FeatureCard 稍后将预览该视图最终的样子。

7、在图像上叠加有关地标的文本信息。

struct FeatureCard: View {var landmark: Landmarkvar body: some View {landmark.featureImage?.resizable().overlay {TextOverlay(landmark: landmark)}}
}struct TextOverlay: View {var landmark: Landmarkvar gradient: LinearGradient {.linearGradient(Gradient(colors: [.black.opacity(0.6), .black.opacity(0)]),startPoint: .bottom,endPoint: .center)}var body: some View {ZStack(alignment: .bottomLeading) {gradientVStack(alignment: .leading) {Text(landmark.name).font(.title).bold()Text(landmark.park)}.padding()}.foregroundStyle(.white)}
}

接下来,创建另一个SwiftUI视图展示遵循UIViewControllerRepresentable协议的视图。

8、创建一个名为PageView.swift的视图,声明一个PageViewController作为子视图。初始化时使用一个视图数组来初始化,并把每一个视图都嵌入在一个UIHostingController中。UIHostingController是一个UIViewController的子类,用来在UIKit环境中表示一个SwiftUI视图。

struct PageView<Page: View>: View {var pages: [Page]var body: some View {PageViewController(pages: pages)}
}#Preview {PageView()
}

预览失败是因为Xcode无法推断Page的类型。

9、添加宽高比修改器,更新预览视图,并传入视图数组,预览视图就会开始工作了。

struct PageView<Page: View>: View {var pages: [Page]var body: some View {PageViewController(pages: pages).aspectRatio(3 / 2, contentMode: .fit)}
}#Preview {PageView(pages: ModelData().features.map { FeatureCard(landmark: $0) })
}

创建视图控制器的数据源

短短几个步骤就做了很多事,PageViewController 使用 UIPageViewController 去展示来自 SwiftUI 内容。现在是时候添加扫动手势进行页面之间的滚动了。

请添加图片描述

一个展示 UIKit 视图控制器的 SwiftUI 视图可以定义一个 Coordinator 类型,这个 Coordinator 类型由SwitUI管理,用来作为视图展示的上下文。

1、在 PageViewControlelr 中定义一个嵌套类型 Coordiantor。SwiftUI管理 UIViewControllerRepresentable 类型的 coordinator,并在调用方法时把它作为上下文的一部分。

    class Coordinator: NSObject {var parent: PageViewControllerinit(_ pageViewController: PageViewController) {parent = pageViewController}}

2、在 PageViewController 中添加另一个方法,创建coordinator。SwiftUI在调用 makeUIViewController(context:) 前会先调用 makeCoordinator() 方法,因此在配置视图控制器时是可以访问到coordiantor对象的。

    func makeCoordinator() -> Coordinator {Coordinator(self)}

可以使用coordinator为实现通用的Cocoa模式,例如:代理模式、数据源以及目标-动作。

3、在 Coordinator 中使用 pages 的视图数组初始化控制器数组。

    func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {pageViewController.setViewControllers([context.coordinator.controllers[0]], direction: .forward, animated: true)}class Coordinator: NSObject {var parent: PageViewControllervar controllers = [UIViewController]()init(_ pageViewController: PageViewController) {parent = pageViewControllercontrollers = parent.pages.map { UIHostingController(rootView: $0) }}}

Coordinator 是存储这些控制器的好地方,因为系统只初始化它们一次,并且在需要它们更新视图控制器之前。

4、让 Coordinator 类型遵循 UIPageViewControllerDataSource 协议,并且实现两个必要方法。这两个必要方法会建立起视图控制器之间的联系,因此可以实现页面之前的前后切换。

    class Coordinator: NSObject, UIPageViewControllerDataSource {var parent: PageViewControllervar controllers = [UIViewController]()init(_ pageViewController: PageViewController) {parent = pageViewControllercontrollers = parent.pages.map { UIHostingController(rootView: $0) }}func pageViewController(_ pageViewController: UIPageViewController,viewControllerBefore viewController: UIViewController) -> UIViewController?{guard let index = controllers.firstIndex(of: viewController) else {return nil}if index == 0 {return controllers.last}return controllers[index - 1]}func pageViewController(_ pageViewController: UIPageViewController,viewControllerAfter viewController: UIViewController) -> UIViewController?{guard let index = controllers.firstIndex(of: viewController) else {return nil}if index + 1 == controllers.count {return controllers.first}return controllers[index + 1]}}

5、把coordiantor作为UIPageViewController的数据源。

    func makeUIViewController(context: Context) -> UIPageViewController {let pageViewController = UIPageViewController(transitionStyle: .scroll,navigationOrientation: .horizontal)pageViewController.dataSource = context.coordinatorreturn pageViewController}

打开实时预览,并测试一下 PageView 前后页面切换的功能是否正常。

在SwiftUI视图的状态下跟踪页面

如果要添加一个自定义的 UIPageControl 控件,就需要一种方式能够在 PageView 中跟踪当前展示的页面。

这就需要在 PageView 中声明一个 @State 属性,并传递一个针对该属性的绑定关系给 PageViewController 视图,在 PageViewController 中通过绑定关系更新状态属性,来反映当前展示的页面。

1、在 PageViewController 中添加一个绑定属性 currentPage。除了使用关键字 @Binding 声明属性为绑定属性外,还需要更新一下函数 setViewControllers(_:direction:animated:),给它传入 currentPage 绑定属性。

    @Binding var currentPage: Intfunc updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {pageViewController.setViewControllers([context.coordinator.controllers[currentPage]], direction: .forward, animated: true)}

2、在PageView中声明 @State变量,并在创建 PageViewController 时把绑定属性传入。注意使用 $ 语法创建一个针对状态变量的绑定关系。

struct PageView<Page: View>: View {var pages: [Page]@State private var currentPage = 0var body: some View {PageViewController(pages: pages, currentPage: $currentPage).aspectRatio(3 / 2, contentMode: .fit)}
}

3、通过改变 PageView 视图中的 currentPage 初始值来测试绑定关系是否正常生效。也可以做一个测试按钮,点击按钮时让第二个页面展示出来。

    @State private var currentPage = 1

4、添加一个TextView控件来展示状态变量currentPage的值,拖动页面切换时观察TextView上的值,目前不会发生变化。因为PageViewController内部没有在切换页面的过程中更新currentPage的值。

struct PageView<Page: View>: View {var pages: [Page]@State private var currentPage = 0var body: some View {VStack {PageViewController(pages: pages, currentPage: $currentPage)Text("Current Page: \(currentPage)")}.aspectRatio(3 / 2, contentMode: .fit)}
}

5、在 PageViewController.swift 中让 coordinator 作为 UIPageViewController 的代理,并添加p ageViewController(_:didFinishAnimating:previousViewControllers:transitionCompleted completed: Bool) 方法。因为 SwiftUI 在页面切换动画完成时会调用这个方法,这样就可以这个方法内部获取当前正在展示的页面的下标,并同时更新绑定属性currentPage的值。

class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate {func pageViewController(_ pageViewController: UIPageViewController,didFinishAnimating finished: Bool,previousViewControllers: [UIViewController],transitionCompleted completed: Bool) {if completed,let visibleViewController = pageViewController.viewControllers?.first,let index = controllers.firstIndex(of: visibleViewController) {parent.currentPage = index}}...

6、coordinator 除了是 UIPageViewController 数据源外,再把它赋值为UIPageViewController的代理。由于绑定关系是双向的,所以当页面切换时,PageView视图上的Text就会实时展示当前的页码。

    func makeUIViewController(context: Context) -> UIPageViewController {let pageViewController = UIPageViewController(transitionStyle: .scroll,navigationOrientation: .horizontal)pageViewController.dataSource = context.coordinatorpageViewController.delegate = context.coordinatorreturn pageViewController}

添加一个自定义PageControl

准备为包裹在 UIViewRepresentable 视图中的子视图上添加了一个自定义 UIPageControl。

请添加图片描述

1、创建一个新的 SwiftUI 视图,命名为 PageControl.swift,并使 PageControl 类型遵循 UIViewRepresentable 协议。UIViewRepresentable 和 UIViewControllerRepresentable 类型有相同的生命周期,在 UIKit 类型中都有对应的生命周期方法。

struct PageControl: UIViewRepresentable {var numberOfPages: Int@Binding var currentPage: Intfunc makeUIView(context: Context) -> UIPageControl {let control = UIPageControl()control.numberOfPages = numberOfPagesreturn control}func updateUIView(_ uiView: UIPageControl, context: Context) {uiView.currentPage = currentPage}
}

2、在 PageView 中用 PageControl 替换 Text ,并把 VStack 换成 ZStack 。因为总页数和当前页面都已经传入 PageControl,所以 PageControl 已经可以正确的显示。

    var body: some View {ZStack(alignment: .bottomTrailing) {PageViewController(pages: pages, currentPage: $currentPage)PageControl(numberOfPages: pages.count, currentPage: $currentPage).frame(width: CGFloat(pages.count * 18)).padding(.trailing)}.aspectRatio(3 / 2, contentMode: .fit)}

下一步要处理PageControl与用户的交互,让它可以被用户点击任意一边进行页面间的切换。

3、在 PageControl 中创建一个嵌套类型 Coordiantor,添加一个 makeCoordinator() 方法创建并返回一个 coordinator 实例。因为 UIControl 子类(包括 UIPageControl)使用 Target-Action 模式,Coordinator 实现一个 @objc 方法来更新 currentPage 绑定属性的值。

    func makeCoordinator() -> Coordinator {Coordinator(self)}class Coordinator: NSObject {var control: PageControlinit(_ control: PageControl) {self.control = control}@objcfunc updateCurrentPage(sender: UIPageControl) {control.currentPage = sender.currentPage}}

4、把 coordinator 作为 PageControl 值改变事件的目标处理器,并指定 updateCurrentPage(sender:) 方法为处理函数。

    func makeUIView(context: Context) -> UIPageControl {let control = UIPageControl()control.numberOfPages = numberOfPagescontrol.addTarget(context.coordinator,action: #selector(Coordinator.updateCurrentPage(sender:)),for: .valueChanged)return control}

5、最后,在 CategoryHome 中,用新的页面视图替换占位符特征图像。

struct CategoryHome: View {@Environment(ModelData.self) var modelData@State private var showingProfile = falsevar body: some View {NavigationSplitView {List {PageView(pages: modelData.features.map { FeatureCard(landmark: $0) }).listRowInsets(EdgeInsets())ForEach(modelData.categories.keys.sorted(), id: \.self) { key inCategoryRow(categoryName: key, items: modelData.categories[key]!)}.listRowInsets(EdgeInsets())}.listStyle(.inset).navigationTitle("Featured").toolbar {Button {showingProfile.toggle()} label: {Label("User Profile", systemImage: "person.crop.circle")}}.sheet(isPresented: $showingProfile) {ProfileHost().environment(modelData)}} detail: {Text("Select a Landmark")}}
}

6、现在就可以尝试 PageControl 的各种交互来切换页面,PageView展示了SwiftUI和UIKit视图如何混合使用。

相关文章:

SwiftUI八与UIKIT交互

代码下载 SwiftUI可以在苹果全平台上无缝兼容现有的UI框架。例如&#xff0c;可以在SwiftUI视图中嵌入UIKit视图或UIKit视图控制器&#xff0c;反过来在UIKit视图或UIKit视图控制器中也可以嵌入SwiftUI视图。 本文展示如何把landmark应用的主页混合使用UIPageViewController和…...

RedHat9 | 内部YUM本地源服务器搭建

服务器参数 标识公司内部YUM服务器主机名yum-server网络信息192.168.37.1/24网络属性静态地址主要操作用户root 一、基础环境信息配置 修改主机名 [rootyum-server ~]# hostnamectl hostname yum-server添加网络信息 [rootyum-server ~]# nmcli connection modify ens160 …...

无偏归一化自适应心电ECG信号降噪方法(MATLAB)

心电信号作为一种生物信号&#xff0c;含有大量的临床应用价值的信息&#xff0c;在现代生命医学研究中占有重要的地位。但心电信号低频、低幅值的特点&#xff0c;使其在采集和传输的过程中经常受到噪声的干扰&#xff0c;使心电波形严重失真&#xff0c;从而影响后续的病情分…...

AI基本概念(人工智能、机器学习、深度学习)

人工智能 、 机器学习、 深度学习的概念和关系 人工智能 &#xff08;Artificial Intelligence&#xff09;AI- 机器展现出人类智慧机器学习 &#xff08;Machine Learning) ML, 达到人工智能的方法深度学习 &#xff08;Deep Learning&#xff09;DL,执行机器学习的技术 从范围…...

LabVIEW幅频特性测试系统

使用LabVIEW软件开发的幅频特性测试系统。该系统整合了Agilent 83732B信号源与Agilent 8563EC频谱仪&#xff0c;通过LabVIEW编程实现自动控制和数据处理&#xff0c;提供了成本效益高、操作简便的解决方案&#xff0c;有效替代了昂贵的专用仪器&#xff0c;提高了测试效率和设…...

校园卡手机卡怎么注销?

校园手机卡的注销流程可以根据不同的运营商和具体情况有所不同&#xff0c;但一般来说&#xff0c;以下是注销校园手机卡的几种常见方式&#xff0c;我将以分点的方式详细解释&#xff1a; 一、线上注销&#xff08;通过手机APP或官方网站&#xff09; 下载并打开对应运营商的…...

logback自定义规则脱敏

自定义规则conversionRule public class LogabckMessageConverter extends MessageConverter {Overridepublic String convert(ILoggingEvent event) {String msg event.getMessage();if ("INFO".equals(event.getLevel().toString())) {msg .....脱敏实现}return …...

高效批量复制与覆盖:一键实现文件管理,轻松应对同名文件,简化工作流程

在数字时代&#xff0c;我们每天都在与海量的文件和数据打交道。你是否曾经遇到过这样的情况&#xff1a;需要批量复制文件到指定文件夹&#xff0c;但一遇到同名文件就头疼不已&#xff0c;要么手动一个个确认覆盖&#xff0c;要么冒着数据丢失的风险直接操作&#xff1f;别担…...

vue3中使用Antv G6渲染树形结构并支持节点增删改

写在前面 在一些管理系统中&#xff0c;会对组织架构、级联数据等做一些管理&#xff0c;你会怎么实现呢&#xff1f;在经过调研很多插件之后决定使用 Antv G6 实现&#xff0c;文档也比较清晰&#xff0c;看看怎么实现吧&#xff0c;先来看看效果图。点击在线体验 实现的功能…...

【PB案例学习笔记】-26制作一个带浮动图标的工具栏

写在前面 这是PB案例学习笔记系列文章的第26篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…...

反向沙箱技术:安全隔离上网

在信息化建设不断深化的今天&#xff0c;业务系统的安全性和稳定性成为各公司和相关部门关注的焦点。面对日益复杂的网络威胁&#xff0c;传统的安全防护手段已难以满足需求。深信达反向沙箱技术&#xff0c;以其独特的设计和强大的功能&#xff0c;成为保障政务系统信息安全的…...

前端在for循环中使用Element-plus el-select中的@click.native动态传参

<el-table ref"table" :data"editTableVariables" cell-dblclick"handleRowDblClick" style"width: 100%" > <!-- el-table-column: 表格列组件&#xff0c;定义每列的展示内容和属性 --><el-table-column prop&q…...

Oracle SQL - CONNECT BY语句Where条件中不能使用OR?[已解决]

数据 SQL> SELECT * FROM demo_a;CUSTOMER TOTAL ---------- ---------- A 100200SQL> SELECT * FROM demo_b;CUSTOMER RN QTY ---------- ---------- ---------- A 1 30 A 2 …...

python-逻辑语句

if else语句 不同于C&#xff1a;else if range语句&#xff1a; continue continue的作用是&#xff1a; 中断所在循环的当次执行&#xff0c;直接进入下一次 continue在嵌套循环中的应用 break 直接结束所在的循环 break在嵌套循环中的应用 continue和break&#xff0c;在…...

【stm32】大一上学期笔记复制

砌墙单片机 外设是什么&#xff1f; ipage 8 nx轴 128 X0-127 y0-63 PWM脉冲宽度调制 PWM脉冲宽度调制 2023年10月13日 基本特性&#xff1a;脉冲宽度调制PWM是一种对模拟信号进行数字编码的方法。广泛引用于电机控制&#xff0c;灯光的亮度调节&#xff0c;功率控制等领域…...

LeetCode题练习与总结:二叉树的前序遍历--144

一、题目描述 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,2,3]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[]示例 3&#xff1a; 输入&#xff1a;roo…...

如何优化Spring Boot应用的性能

如何优化Spring Boot应用的性能 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨如何通过优化技术和最佳实践来提升Spring Boot应用的性能&#x…...

人工智能--目标检测

欢迎来到 Papicatch的博客 文章目录 &#x1f349;引言 &#x1f349;概述 &#x1f348;目标检测的主要流程通常包括以下几个步骤 &#x1f34d;数据采集 &#x1f34d;数据预处理 &#x1f34d;特征提取 &#x1f34d;目标定位 &#x1f34d;目标分类 &#x1f348;…...

Java基础之List实现类

文章目录 一、基本介绍二、常见方法三、ArrayList注意事项四、ArrayList底层结构我的理解 五、ArrayList扩容机制无参构造器有参构造器 六、LinkedList介绍底层操作机制 七、ArrayList 与 LinkedListArrayListLinkedList tip&#xff1a;以下是正文部分 一、基本介绍 List集合…...

java List接口介绍

List 是 Java 集合框架中的一个接口,它继承自 Collection 接口,代表一个有序的元素集合。List 允许重复的元素,并且可以通过索引来访问元素。Java 提供了多种 List 的实现,如 ArrayList、LinkedList、Vector 和 CopyOnWriteArrayList。 List接口概述 List 接口提供了一些…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...