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

iOS--RunLoop原理

前言

曾经在写项目的时候遇到过这么一个问题。:

项目中添加了一个tableview,然后还有一个计时器,当滑动tableview的时候会阻塞计时器,你得执行这么一段代码后,计时器才能正常运行。

RunLoop.current.add(timer, forMode: .common)

发生这种情况是因为我在defaultRunLoopMode上隐式创建计时器,这实际上是我们应用程序的主线程。然后,当用户积极与我们的用户界面互动时,这将暂停,然后在他们停止时重新激活。

什么是runloop呢?

RunLoop是一个事件循环机制,用于管理线程中的事件和消息。它允许线程在没有任务的情况下休眠,并在有任务需要处理时唤醒线程。 RunLoop主要负责以下几个方面:

  • 处理输入源:RunLoop负责处理输入源,包括用户界面事件、触摸事件、定时器事件、网络事件等,通过RunLoop能够有效地处理这些事件,让应用程序的响应更加及时。

  • 保持线程活动(线程保活):RunLoop能够保持线程活动,即使在没有任务时,RunLoop也会让线程休眠而不会退出,以便随时处理来自输入源的事件。

  • 定时器功能:RunLoop提供了一些定时器功能,例如延迟执行和重复执行某个任务。通过定时器功能,可以很方便地在指定时间执行任务。

  • 优化性能:RunLoop能够优化应用程序的性能,通过RunLoop能够让应用程序在有任务需要处理时及时唤醒线程,而在没有任务时让线程休眠,从而避免了线程的空转,减少了CPU的占用,提高了应用程序的性能。

runloop和线程之间的关系

  • 每条线程都有唯一的一个与之对应的RunLoop对象
  • RunLoop保存在一个全局的Dictionary里,线程作为key,RunLoop作为value
  • 线程刚创建时并没有RunLoop对象,RunLoop会在第一次获取它时创建
  • RunLoop会在线程结束时销毁
  • 主线程的RunLoop已经自动获取(创建,用于响应UI和用户交互事件),子线程默认没有开启RunLoop

runloop的基本组成

  • Input Source(输入源):

        异步事件的通道,如用户交互(手势、触摸)、网络请求等。

  • Timer Source(定时器源):

        定时任务,如 NSTimer,它会定期触发某个操作。RunLoop 会定期检查定时器,并在时间到达时触发相应的操作。

  • Observer(观察者):

        监听 RunLoop 状态的变化,如启动、休眠、唤醒、退出等。可以用于监控 RunLoop 的执行过程,便于调试或优化。

        以下是Observer(观察者)的常见状态:

  1. kCFRunloopEntry (runloop准备启动)
  2. kCFRunloopBeforeTimers (通知观察者,runloop将要对Timer的一些相关事件进行处理了)
  3. kCFRunloopBeforeSources (将要处理一些Sources事件)
  4. kCFRunloopBeforeWaiting( 即将要发生用户态到内核态的切换 用户态 —> 内核态)没事做进入内核态避免资源浪费
  5. kCFRunloopAfterWaiting (内核态—转—>用户态)
  6. kCFRunloopExit (runloop退出通知)

        简单来说就是,runloop从用户态切换到内核态可以节省系统资源,使得线程在没有任务时不会浪费 CPU 时间。

RunLoop 通过监听输入源、定时器源、观察者来处理和调度事件,确保线程可以在处理完事件后及时进入休眠。

runloop的不同模式

runloop可以根据所需切换成不同的模式:

  1. NSDefaultRunLoopMode :默认模式,处理大多数应用事件,如 Timer定时器触发、网络事件等。
  2. UITrackingRunLoopMode :UI模式,专门处理UI事件
  3. NSRunLoopCommonModes :常用模式,允许 RunLoop 同时处理多种事件类型。使用场景包括当用户滚动 UIScrollView 时仍能处理定时器事件。
  4. UIInitializationRunLoopMode :在刚启动App时第进入的第一个Mode,启动完成后就不再使用
  5. GSEventReceiveRunLoopMode :接受系统事件的内部Mode

示例:

let timer = Timer(timeInterval: 1.0, repeats: true) { _ inprint("Timer fired during scroll")
}
//将定时器添加到 .common 模式中,确保在滚动时仍能触发
RunLoop.current.add(timer, forMode: .common)

将Timer定时器添加到.common模式中才能在ScrollView滚动时响应的原理:

  • 当应用处于空闲状态时,RunLoop 处于 NSDefaultRunLoopMode(默认模式),它处理正常任务,包括 Timer 的回调、用户输入等。
  • 当用户与 ScrollView 交互时,RunLoop 切换到 UITrackingRunLoopMode(UI模式),在这种模式下,RunLoop 只处理与用户交互相关的任务,确保滑动的流畅性。此时,未被标记为 “Common” 的 Timer 和其他事件源会被暂时忽略。
  • 如果 Timer 只添加到 NSDefaultRunLoopMode(默认模式),滑动时(UITrackingRunLoopMode)它将不会触发,直到滑动结束后 RunLoop 切换回 DefaultMode,Timer才会被继续触发。
  • 使用 NSRunLoopCommonModes(常用模式) 可以让 Timer 在所有标记为 “Common” 的模式下执行,保证用户滑动时依然能触发回调。

tips:Common模式默认将runloop添加到NSDefaultRunLoopMode和UITrackingRunLoopMode模式。

runloop的循环流程

  1. 检查并处理输入源事件。
  2. 检查并处理定时器事件。
  3. 如果没有任务,进入休眠等待新的事件。
  4. 当有事件到来时,唤醒并处理事件。
  5. 重复以上过程,直到 RunLoop 退出。

用户态: 是指应用程序执行的状态。RunLoop 在这个状态下负责处理任务(如用户交互、定时器)。

内核态: 当 RunLoop 没有任务时,它会进入内核态,等待新的事件。这个时候,线程会进入休眠,操作系统负责监控任务的到达,以减少 CPU 资源的消耗。

runloop的Input Source(输入源)分类

1.Source0(非基于 port 的事件源):

        Source0 是应用程序主动触发的事件源。它不依赖系统的 port 机制,也不会自动唤醒 RunLoop。这类事件通常是应用内部主动触发的事件,比如用户点击了按钮、触摸屏幕或某个任务完成后调用的回调函数。

特点:

  • 需要手动触发。
  • RunLoop 无法通过 Source0 自动唤醒,必须配合其他机制(如 Source1)来激活。

2.Source1(基于 port 的事件源):

        Source1 是基于 port 机制的事件源,用于处理操作系统内核级别的事件它负责监听操作系统内核发出的事件或消息(如网络 I/O、文件 I/O 等),并通过 port 机制唤醒 RunLoop,然后分发这些事件进行处理。

特点:

  • 基于 port 通信,可以自动唤醒 RunLoop。
  • 用于系统内部和外部进程的消息传递。

总的来说,Source0负责处理应用程序内部的主动事件(用户点击、任务回调等),需要其他机制(Soruce1)唤醒 RunLoop。而Source1 处理基于 port 的系统内核事件(例如进程间通信、网络事件等),并负责唤醒 RunLoop。

举个例子:

我们触摸屏幕,屏幕表面的事件会先包装成Event,Event先告诉source(输入源)(通过mach_port机制),Source1唤醒RunLoop,然后将事件Event分发给Source0,然后由Source0来处理。

事件处理完成后,如果没有新的事件或定时器触发,RunLoop 会再次进入休眠状态,直到下一个事件发生。

iOS使用RunLoop实现的功能

AutoreleasePool

自动释放池的创建和释放,销毁的时机如下所示:

  • kCFRunLoopEntry; // 进入runloop之前,创建一个自动释放池
  • kCFRunLoopBeforeWaiting; // 休眠之前,销毁自动释放池,创建一个新的自动释放池
  • kCFRunLoopExit; // 退出runloop之前,销毁自动释放池

 RunLoop 机制的事件响应流程

1. 硬件事件的产生和传递

当一个硬件事件发生时(例如用户触摸屏幕、按下按钮、摇晃设备等),硬件事件被系统底层的 IOKit.framework 捕获,并生成一个 IOHIDEvent 事件。这个事件首先被 SpringBoard 进程接收。SpringBoard 是 iOS 的系统进程,负责处理与设备交互相关的硬件事件,例如锁屏、静音等。

然后,SpringBoard 通过 mach_port 将事件传递给目标 App 的进程。App 中的 RunLoop 会监听来自系统的这些事件。当事件到达时,RunLoop 中注册的 Source1 事件源被触发,唤醒 RunLoop,并执行回调来处理这些事件。

2. _UIApplicationHandleEventQueue() 函数

在事件进入应用进程后,_UIApplicationHandleEventQueue() 函数负责对事件进行处理和分发。例如:

• 将触摸事件包装成 UIEvent 对象。

• 识别触摸的手势是否属于点击、拖拽、缩放等。

• 处理 UI 的交互,比如按钮点击、屏幕旋转等。

如果是常规事件,比如用户点击了一个按钮,系统会通过此函数找到事件的响应目标,比如 UIButton,并触发相应的回调函数。

手势识别

手势事件的识别过程:

• 当 _UIApplicationHandleEventQueue() 识别到某个手势时,它会取消当前的触摸事件处理(比如 touchesBegan、touchesMoved),并标记对应的 UIGestureRecognizer 为“待处理”状态。

• 苹果系统内部注册了一个 RunLoop 观察者,用来监听 BeforeWaiting 阶段(即 RunLoop 即将进入休眠状态)。当 RunLoop 进入这个状态时,观察者的回调 _UIGestureRecognizerUpdateObserver() 会被触发。

• 在这个回调中,系统会处理所有刚标记为“待处理”的手势识别器,执行它们的相应回调函数。比如,用户的双击、滑动等手势就是在这个阶段被识别并处理的。

总结: 手势识别是在 RunLoop 准备进入休眠前的最后阶段进行处理的,这样可以保证手势识别的优先级较高。

页面更新

当我们更新界面(例如修改视图的 frame,或调用 setNeedsLayout / setNeedsDisplay 方法)时,UIView 或 CALayer 会被标记为“待处理”,并加入到系统的待处理队列中。

苹果系统内部同样注册了一个 RunLoop 观察者,用来监听 BeforeWaiting 和 Exit 阶段。当 RunLoop 进入这些状态时,回调 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv() 被触发,系统会遍历所有标记为待处理的视图或图层,执行布局更新和重绘操作。

优化提示:

通过将界面更新操作推迟到 RunLoop 休眠前的阶段,可以避免在用户交互时立即刷新界面,从而提高界面响应速度。

定时器NSTimer

NSTimer 工作原理:

• NSTimer 是基于 RunLoop 的定时器,底层实现为 CFRunLoopTimerRef。当你创建一个 NSTimer 并将其添加到 RunLoop 中时,RunLoop 会为定时器注册好未来的触发时间点。

• 定时器回调并不总是会在非常准确的时间点触发,因为 RunLoop 会对定时器进行一些优化。定时器有一个 tolerance 参数,允许指定触发时间的最大误差。这样可以在保证性能的前提下,避免系统资源的浪费。

时间点的错过:

如果在某个时间点执行了一个较长的任务,RunLoop 可能会错过该时间点,直接跳到下一个时间点,而不会延后执行。例如,如果 NSTimer 设置为每 10 秒触发一次,但是某次因为执行长时间任务导致错过了 10:00 的触发点,那么定时器会直接在下一个 10:10 的时间点触发。

总的来说:

1. 事件响应:通过 Source1 唤醒 RunLoop,然后通过 Source0 分发事件。

2. 手势识别:在 BeforeWaiting 阶段处理,优先级较高。

3. 界面更新:在 BeforeWaiting 或 Exit 阶段进行 UI 布局和重绘优化。

4. 定时器:NSTimer 和 CADisplayLink 都通过 RunLoop 处理,注意定时器的容忍度和长时间任务对动画和定时器的影响。

RunLoop实践

1.runloop可以做什么

  • 处理Crash(程序崩溃不退出)
  • 保持线程存活(线程保活)
  • 监测和优化App的卡顿

线程保活(NSOperation和GCD一样可以)(NSCondition加锁保活,不涉及RunLoop)
​ 如果项目需求比较复杂,很多操作都需要在子线程进行,比如有很多耗时操作(图片绘制,视频下载等等),子线程执行完任务之后会自动销毁,频繁的线程创建和销毁会导致资源浪费,此时就可以使用RunLoop进行线程保活而不被销毁。我们知道,当子线程中的任务执行完毕之后就被销毁了,那么如果我们需要开启一个子线程,在程序运行过程中永远都存在,那么我们就会面临一个问题,如何让子线程永远活着,这时就要用到常驻线程:给子线程开启一个RunLoop 注意:子线程执行完操作之后就会立即释放,即使我们使用强引用子线程使子线程不被释放,也不能给子线程再次添加操作,或者再次开启。 子线程开启RunLoop的代码,先点击屏幕开启子线程并开启子线程RunLoop,然后点击button。

2.runloop组成

sources/timer/observer(卡顿检测)

其中我们可以通过 RunLoop 的 Observer 机制来检测卡顿。具体思路是:

监听 RunLoop 的状态变化。当 RunLoop 处于不同状态时,比如准备处理 Timer、Source、等待事件(进入休眠)、处理事件后等,都可以通过注册相应的回调函数来监听。

监控 RunLoop 在处理任务时的时间消耗。如果某个状态持续时间过长(例如在 BeforeWaiting 或 AfterWaiting 状态之间执行任务时超过了一定的阈值),可以认为主线程出现了卡顿。

卡顿优化的话,可以通过将耗时任务移到后台线程、合理使用 NSTimer(适当调整 tolerance(宽容度),可以减少系统资源消耗)、推迟界面更新(线程保活)等方式,可以有效优化卡顿现象,提升应用的流畅度。

影响卡顿的因素:

卡顿跟硬件有关:CPU、GPU

影响CPU性能:IO任务,过多的线程抢占CPU资源、温度过高降频

影响GPU性能:显存频率、渲染算法、大计算量

参考:

https://github.com/miaoqiu/RunLoop?tab=readme-ov-file#%E6%8C%89%E7%85%A7%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3source%E7%9A%84%E5%88%86%E7%B1%BB

https://github.com/yanmingLiu/iOSNotes?tab=readme-ov-file#3-runloop

Runloop解析_objective-c runloop-CSDN博客

RunLoop in details | kyryl horbushko

相关文章:

iOS--RunLoop原理

前言 曾经在写项目的时候遇到过这么一个问题。: 项目中添加了一个tableview,然后还有一个计时器,当滑动tableview的时候会阻塞计时器,你得执行这么一段代码后,计时器才能正常运行。 RunLoop.current.add(timer, for…...

并查集——从LeetCode题海中总结常见套路

目录 并查集定义 LeetCode128.最长连续序列 先去重再sort: 改进去重的方法: 参考: 并查集定义 在计算机科学中,并查集是一种树型的数据结构,用于处理一些不交集(Disjoint Sets)的合并及查…...

深入理解作用域【JavaScript】

一、作用域的内部原理 JavaScript 的作用域机制是理解变量如何被访问和存储的重要概念。下面详细介绍作用域的内部原理,包括编译、执行、查询、嵌套和异常处理这五个步骤。 1. 编译 在 JavaScript 的执行过程中,首要的步骤是编译。尽管JavaScript是解…...

微信小程序实战教程:如何使用map组件实现地图功能

在微信小程序中,map组件是一个非常实用的功能,它可以帮助我们快速实现地图展示、定位、标注等操作。本文将详细介绍如何在微信小程序中使用map组件,带你轻松掌握地图开发技能。 一、map组件概述 map组件是微信小程序官方提供的一个地图组件…...

张雪峰谈人工智能技术应用专业的就业前景!

一、张雪峰谈人工智能技术应用专业 在教育咨询领域,张雪峰老师以其深入浅出的讲解和前瞻性的视角,为广大学子提供了宝贵的专业选择建议。对于人工智能技术应用专业,张雪峰老师通常给予高度评价,认为这是一个充满无限可能且就业前…...

机器学习课程学习周报十五

机器学习课程学习周报十五 文章目录 机器学习课程学习周报十五摘要Abstract一、机器学习部分1. 统计推断与贝叶斯推断2. GMM和EM算法补充3. 马尔可夫链蒙特卡罗法3.1 蒙特卡罗法3.2 马尔可夫链3.3 Diffusion模型中的马尔可夫链 总结 摘要 本周的学习涵盖了统计推断和贝叶斯推断…...

rabbitMq------客户端模块

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言消费者模块信道管理模块管理的字段提供的接口 信道内存管理连接管理类 前言 在RabbitMQ中,提供服务的是信道,因此在客⼾端的实现中&…...

地理定位营销与开源AI智能名片O2O商城小程序的融合与发展

摘要:本文阐述地理定位营销的概念、手段及其在商业中的应用,探讨开源AI智能名片O2O商城小程序如何与地理定位营销相结合,为企业营销带来新的机遇与挑战。 一、引言 在当今数字化营销的时代,地理定位营销已成为一种重要的营销手段…...

解决Vue应用中遇到路由刷新后出现 404 错误

解释: Vue 应用中遇到路由刷新后出现 404 错误,通常是因为 Vue 应用是个单页应用(SPA),它通过 Vue Router 管理路由,通过 HTML5 History Mode 实现页面导航无需重新加载页面。当直接访问非首页的路由或者刷…...

在window10下使用directml加速phi-3模型的一些记录

1.安装anaconda,安装python 安装torch等参考网上资料非常多 不细描述 2.参考微软官网【在windows上通过DirectML启用Pytorch文档,检查系统版本 检查gpu版本 3.参考微软官网【在windows上通过DirectML启用Pytorch】文档,安装torch_directml模…...

通信工程学习:什么是OSPF开放式最短路径优先

OSPF:开放式最短路径优先 OSPF(Open Shortest Path First,开放式最短路径优先)是一种内部网关协议(IGP),被广泛应用于计算机网络中,特别是在构建大型和复杂的网络时。以下是对OSPF的…...

《中国电子报》报道: 安宝特AR为产线作业者的“秘密武器

近日,中国电子报在其文章《下一代工业智能终端重新定义制造业》中对安宝特的增强现实(AR)解决方案给予了高度评价,称其为产线作业者的“秘密武器”。这一创新技术改变了传统制造业的作业方式,使得操作人员能够在生产过…...

【Android】Handler消息机制

文章目录 前言概述核心组件概述Android消息机制概述 Android消息机制分析ThreadLocal的工作原理ThreadLocal基础ThreadLocal实现原理 MessageQueueLooperHandler的工作原理总结 前言 本文用于记录Android的消息机制,主要是指Handler的运行机制。部分内容参考自《An…...

大数据必懂知识点:Parquet、ORC还是Avro作为数据存储格式,哪种在性能和压缩率上更优

目录 第一章 相关理论 1.1 Parquet格式介绍 1.1.1 起源与发展 1.1.2 特点与优势 1.2 ORC格式介绍 1.3 Avro格式介绍 1.3.1 跨语言支持 1.3.2 动态映射 1.3.3 丰富的数据模式 1.3.4 数据模式灵活性 第二章 种格式性能比较 2.1 读写性能对比 2.2 查询性能对比 2.3 压…...

P1387 最大正方形

题目描述 在一个nm 的只包含 0 和 1 的矩阵里找出一个不包含 0 的最大正方形,输出边长。 输入格式 输入文件第一行为两个整数n,m(1≤n,m≤100),接下来 n 行,每行 m 个数字,用空格隔开,0 或 1。 输出格式 一个整数…...

Python知识点:如何使用Multiprocessing进行并行任务管理

开篇,先说一个好消息,截止到2025年1月1日前,翻到文末找到我,赠送定制版的开题报告和任务书,先到先得!过期不候! 如何在Python中使用Multiprocessing进行并行任务管理 在现代编程中,…...

React常见优化问题

在React开发中,性能优化是一个重要且持续的过程,旨在提升应用的响应速度和用户体验。以下是一些常见的React优化问题详解,并附上相应的代码示例。 1. 避免不必要的组件渲染 React组件的渲染是由其props或state的变化触发的。但是,…...

css 简单网页布局——浮动(一)

1. 三种布局方式 1.1 标准流 1.2 浮动的使用 1.3 简述浮动 1.3.1 浮动三大特性 <style>.out {border: 1px red solid;width: 1000px;height: 500px;}.one {background-color: aquamarine;width: 200px;height: 100px;}.two {background-color: blueviolet;width: 200px;h…...

设计模式(3)builder

需求&#xff1a; 对于复杂的对象&#xff0c;我们只需要 通过 设置一些参数&#xff0c;就可以得到相对应的 实例。 简单来说&#xff0c; 需求就是用一个类 通过方法返回一个 新建的对象&#xff0c;而且可以通过方法去设置这个对象 public interface CarBuilder {void se…...

Day01-MySQL数据库介绍及部署

Day01-MySQL数据库介绍及部署 1、数据库服务概述介绍1.1 企业中为什么需要数据库&#xff1f;1.2 数据库服务作用1.3 数据库服务分类 2、数据库服务安装部署2.1 数据库版本应用2.2 数据库服务程序下载2.3 数据库软件安装方式2.3.1 二进制安装步骤 3、数据库服务初始化介绍3.1 安…...

分享一个餐饮连锁店点餐系统 餐馆食材采购系统Java、python、php三个版本(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…...

解决跨域问题

第一种 让后端解决 第二种 通过代理来解决 首先可以先搭建后端接口 解决则参照vue-cli官网 首先新建一个vue.config.js文件 然后在项目的根目录新建两个文件夹 开发环境和生产环境 然后可以使用环境变量 系统会自动识别你是生产环境还是开发环境 然后在封装的axios中配…...

面试知识储备-多线程

1.线程的概念 线程使得在一个程序中可以同时执行多个任务。在 Java 应用程序中&#xff0c;多个线程可以同时运行&#xff0c;例如一个线程可以处理用户输入&#xff0c;另一个线程可以进行后台数据处理。 2.创建线程的方式 &#xff08;1&#xff09;重写thread类中的run方法…...

边缘计算插上AI的翅膀会咋样?

人工智能&#xff08;Artificial Intelligence,AI&#xff09;是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学&#xff0c;是新一轮产业革命的重要驱动力量。2022年底发布的ChatGPT将人工智能技术上升到了一个新的高度。如今&#x…...

脉冲神经网络(SNN)论文阅读(六)-----ECCV-2024 脉冲驱动的SNN目标检测框架:SpikeYOLO

原文链接&#xff1a;CSDN-脉冲神经网络&#xff08;SNN&#xff09;论文阅读&#xff08;六&#xff09;-----ECCV-2024 脉冲驱动的SNN目标检测框架&#xff1a;SpikeYOLO Integer-Valued Training and Spike-Driven Inference Spiking Neural Network for High-performance …...

周报_2024/10/6

周报 时间 2024/9/30——2024/10/6 科研进展 写项目标书 实验了不同比例的标签加噪&#xff0c;模型效果随着标签加噪比例增加下降明显 下周计划 构造概念漂移数据集 借鉴其他文章中应对标签加噪的做法...

[深度学习][python]yolov11+bytetrack+pyqt5实现目标追踪

【算法介绍】 YOLOv11、ByteTrack和PyQt5的组合为实现高效目标追踪提供了一个强大的解决方案。 YOLOv11是YOLO系列的最新版本&#xff0c;它在保持高检测速度的同时&#xff0c;通过改进网络结构、优化损失函数等方式&#xff0c;提高了检测精度&#xff0c;能够同时处理多个…...

如何使用ssm实现基于Web的穿戴搭配系统的设计与实现+vue

TOC ssm784基于Web的穿戴搭配系统的设计与实现vue 第1章 绪论 1.1 研究背景 互联网概念的产生到如今的蓬勃发展&#xff0c;用了短短的几十年时间就风靡全球&#xff0c;使得全球各个行业都进行了互联网的改造升级&#xff0c;标志着互联网浪潮的来临。在这个新的时代&…...

JavaScript的设计模式

JavaScript设计模式是指在面向对象编程中&#xff0c;通过对类和对象进行抽象和泛化&#xff0c;提取出一些通用的设计思路和解决方案&#xff0c;以解决常见的软件设计问题。这些设计模式可以分为以下几类进行详细介绍&#xff1a; 一、创建型模式 1. 工厂模式&#xff08;F…...

CIKM 2024 | 时空数据(Spatial-temporal)论文总结

CIKM 2024于10月21号-10月25号在美国爱达荷州博伊西举行&#xff08;Boise, Idaho, USA&#xff09; 本文总结了CIKM 2024有关时空数据&#xff08;spatial-temporal data&#xff09;的相关论文&#xff0c;主要包含交通预测&#xff0c;插补&#xff0c;事故预测&#xff0c…...