「iOS」通过CoreLocation Framework深入了解MVC架构
「iOS」通过CoreLocation Framework重新了解多界面传值以及MVC架构
文章目录
- 「iOS」通过CoreLocation Framework重新了解多界面传值以及MVC架构
- 前言
- CoreLocation了解
- 根据需求建模
- 设计属性
- 方法设计
- 协议传值
- Block传值
- KVO
- Notification通知方式
- 总结
- 参考文章
前言
在这个学期的前段时间进行了MVC的相关学习,并且使用MVC完成了知乎日报奥的项目,加上学习的一些博客,开始对MVC这个架构有着更加深刻的理解,也体会到了MVC架构之中的缺点,这篇文章就是利用CoreLocation 这个原生关于定位的架构,来总结MVC的一些使用技巧和理解。
CoreLocation了解
根据需求建模
我们可以先来认识CoreLocation
实现定位的相关内容,我们知道CoreLocation
是一个关于位置定位的库,我们分析一下相关的功能,要想实现定位首先就需要一个位置类来对位置进行描述,属于它的属性应该有经纬度,海拔等相关信息;一个地标类来描述所处位置的城市街道;一个管理器来控制位置的变更,以及位置的获取;一个解析器根据当前的位置信息转化为地标。那么逻辑如此,对应的图片关系如下
我们可以在CoreLocation Framework
之中找到了对应的这几个类的相关属性,这里我简单的给出这些类之中的部分头文件
CLLocation
:
@interface CLLocation : NSObject <NSCopying, NSSecureCoding> @property(readonly, nonatomic) CLLocationCoordinate2D coordinate;//返回当前位置的坐标。
@property(readonly, nonatomic) CLLocationDistance altitude;// 返回位置的高度,正值表示海平面上,负值表示海平面下。- (instancetype)initWithLatitude:(CLLocationDegrees)latitudelongitude:(CLLocationDegrees)longitude;//初始化指定经纬度的位置。@end
CLPlacemark
:
@interface CLPlacemark : NSObject <NSCopying, NSSecureCoding>// 通过已有地标初始化新地标并复制其数据
- (instancetype)initWithPlacemark:(CLPlacemark *) placemark;// 获取与地标相关联的地理位置信息
@property (nonatomic, readonly, copy, nullable) CLLocation *location;// 城市名称(如Cupertino)
@property (nonatomic, readonly, copy, nullable) NSString *locality;
......
// 一系列地标相关的具体属性,用于更详细地描述位置信息
CLLocationManager
:
@interface CLLocationManager : NSObject
// 获取调用应用的当前授权状态
@property (nonatomic, readonly) CLAuthorizationStatus authorizationStatus API_AVAILABLE(ios(14.0), macos(11.0), watchos(7.0), tvos(14.0));// 获取最后接收到的位置信息,在接收到位置前为nil
@property(readonly, nonatomic, copy, nullable) CLLocation *location;// 判断用户是否启用了位置服务
+ (BOOL)locationServicesEnabled API_AVAILABLE(ios(4.0), macos(10.7));// 开始更新位置信息
- (void)startUpdatingLocation API_AVAILABLE(watchos(3.0)) API_UNAVAILABLE(tvos);// 停止更新位置信息
- (void)stopUpdatingLocation;@end
CLGeocoder
:
// 定义地理编码完成后的回调处理块,CLPlacemarks按可信度从高到低排列
@interface CLGeocoder : NSObject
typedef void (^CLGeocodeCompletionHandler)(NSArray< CLPlacemark *> * __nullable placemarks, NSError * __nullable error);@interface CLGeocoder : NSObject
// 判断是否正在进行地理编码操作
@property (nonatomic, readonly, getter=isGeocoding) BOOL geocoding;// 反向地理编码请求,根据给定位置获取对应的地标信息
- (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler;// 用地址字符串进行地理编码(默认无区域和首选语言环境设置)
- (void)geocodeAddressString:(NSString *)addressString completionHandler:(CLGeocodeCompletionHandler)completionHandler;
@end
CLLocationManagerDelegate
:
@protocol CLLocationManagerDelegate<NSObject>- (void)locationManager:(CLLocationManager *)managerdidUpdateLocations:(NSArray<CLLocation *> *)locations;@end
设计属性
我们可以从这些类的设计学习一些MVC架构的设计思想
从刚刚的头文件我们可以看到,其实头文件之中的许多属性是被标注为只读,标志为只读其实对于解耦合实现规范代码有着很大的帮助,比如CLLocationManager
之中的location
属性,因为这个位置管理器只是用来管理这个当前的位置,对于外部的使用者来说,只需要在适当的时候进行访问而不是修改。对应数据的更新和维护其实就是这个类内部的负责。
我们就可以提炼出一个设计准则:外部使用者只要负责读取数据,具体的数据更新则是由提供者来完成
这种设计思想其实很清晰的将层次分开了,我们这样不仅成功保护了相关数据的安全,也能进一步的减少相关属性值的滥用。
具体的操作大佬的博客归结为:
- 业务类中的属性设计为只读。使用者只能通过属性来读取数据。而由业务类中的方法内部来更新这些属性的值。
- 数据模型类中的属性定义最好也设置为只读,因为数据模型的建立是在业务类方法内部完成并通过通知或者异步回调的方式交给使用者。而不应该交由使用者来创建和更新。
- 数据模型类一般提供一个带有所有属性的init初始化方法,而初始化后这些属性原则上是不能被再次改变,所以应该设置为只读属性。
这里的类全部指的是暴露在头文件之中的属性声明
至于对于类内容,我们需要在内部(即.m文件)修改相关的声明
@interface CLLocationManager ()@property(nonatomic, copy, nullable) CLLocation *location;
@end//也可以改用以下形式
@implementation CLLocationManager {CLLocation *_location;
}@end
方法设计
协议传值
当我们类设计结束之后,随之而来的就是类方法的设计类。无论如何,我们的业务模型最后总是会走向网络请求或者数据库调用这种需要,在获取操作之后再进行异步的操作。在这里CoreLocation
的框架,使用的是Delegate和Blockzhe这两种方式进行回调
先看CLLocationManager定义的属性
@property(assign, nonatomic, nullable) id<CLLocationManagerDelegate> delegate;
这个协议实现了
@protocol CLLocationManagerDelegate<NSObject>@optional
- (void)locationManager:(CLLocationManager *)managerdidUpdateLocations:(NSArray<CLLocation *> *)locations API_AVAILABLE(ios(6.0), macos(10.9));@end
当位置管理器对象更新了当前的位置后就会调用delegate属性所指对象的didUpdateLocations方法来通知。
这就产生了几个问题:
-
谁来创建M层的位置管理对象?
C层,这个其实很简单,控制器是负责控制和协调M层,所以C层具有负责创建并持有M层对象的责任,C层也是一个使用观察者。 -
M层如何来实现实时的更新和停止更新?
对于位置管理器之中,有以下两个方法
- (void)startUpdatingLocation API_AVAILABLE(watchos(3.0)) __TVOS_PROHIBITED;- (void)stopUpdatingLocation;
好像是在tableView也有相似的两个方法beginUpdates
和endUpdates
,通过方法通知tableView的数据源发生更新进而更新cell。位置管理器之中的这两个方法通过通知管理器,位置类的数据(即M层)在内部发生变化。至于这个两个方法是如何实现位置管理器之中持有的位置类的变化,就是内部实现的内容,相当于一个黑盒,我们作为M层的使用者不需要知道里面的实现原理。
-
谁来负责调用M层提供的那些方法?
答案是: 控制器C层。因为控制器既然负责M层对象的构建,那他当然也是负责M层方法的调用了。 -
谁来观察M层的数据变化通知并进行相应的处理?
答案是: 控制器C层。因为C层既然负责调用M层所提供的方法,那么他理所当然的也要负责对方法的返回以及更新进行处理。在这里我们的C层控制器需要实现CLLocationManagerDelegate接口,并赋值给位置管理器对象的delegate属性。
这里引用大佬博客之中的内容
我们知道MVC结构中,C层是负责协调和调度M和V层的一个非常关键的角色。而C和M以及V之间的交互协调方式用的最多的也是通过Delegate这种模式,Delegate这种模式并不局限在M和C之间,同样也可以应用在V和C之间。Delegate的本质其实是一种双方之间通信的接口,而通过接口来进行通信则可以最大限度的减少对象之间交互的耦合性。
Block传值
除了用Delegate外,我们还可以用Block回调这种方式来实现方法调用的异步通知处理。标准格式如下:
typedef void (^BlockHandler)(id obj, NSError * error);
在地标解析器CLGeocoder之中,采用的就是block回调这种方式来实现异步通知的。我们来看看类的部分定义:
typedef void (^CLGeocodeCompletionHandler)(NSArray< CLPlacemark *> * __nullable placemarks, NSError * __nullable error);// 反向地理编码请求,根据给定位置获取对应的地标信息
- (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler;// 用地址字符串进行地理编码(默认无区域和首选语言环境设置)
- (void)geocodeAddressString:(NSString *)addressString completionHandler:(CLGeocodeCompletionHandler)completionHandler;
从反向地理编码请求可以看出来,我们根据一个CLLocation
方向解码出一个CLPlacemark
的对象,用一个block来完成内容的回调
//VC中的某个点击按钮事件:-(void)ClickHandle:(UIButton*)sender
{sender.userInteractionEnabled = NO;__weak XXXVC *weakSelf = self;//geocoder也可以是XXXVC里面的一个属性,从而可以避免重复建立CLGeocoder *geocoder = [CLGeocoder new];//假设知道了某个位置对象location[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray< CLPlacemark *> * placemarks, NSError * error)){if (weakSelf == nil)return;sender.userInteractionEnabled = YES;if (error == nil){//处理placemarks对象}else{//处理错误}}];
}
这里的block回调,其实在没有异步的情况下(即读取本地库)是可以不需要写的,但是在我们实际的编写过程当中,还是尽可能的遵循统一的相关的模式,有时候需求是会改变的,如果我们这个操作要改为异步操作的话,那么代码需要整段修改,还包括C层的代码,修改起来很麻烦。那么不如就在一开始就使用block进行回调,有统一的格式以及便于理解的优点。
KVO
上面简单展示了Delegate与Block机制用于实现M层数据的更新,前面介绍了这两个机制的优点,下面引用博客的内容,概括这两者的缺点,顺带引入对应的KVO机制监听的内容:
Delegate的方式必须要事先定义出一个接口协议来,并且调用者和实现者都需要按照这个接口规则来进行通知和数据处理交互,这样无形中就产生了一定的耦合性。也就是二者之间还是具有隐式的依赖形式。不利于扩展和进行完全自定义处理。
block方式的缺点则是使用不好则会产生循环引用的问题从而产生内存泄露,另外就是用block机制在出错后难以调试以及难以进行问题跟踪。 而且block机制其实也是需要在调用者和实现之间预先定义一个标准的BlockHandler接口来进行交互和处理。block机制还有一个缺陷是会在代码中产生多重嵌套,从而影响代码的美观和可读性。
Delegate和block方式虽然都是一种观察者实现,但却不是标准和经典的观察者模式。因为这两种模式是无法实现多观察者的。也就是说当数据更新而进行通知时,只能有一个观察者进行监听和处理,不能实现多个观察者的通知更新处理。
可惜的是在CoreLocation Framework并不支持KVO之中方式,下面是大佬假设其支持KVO写出的相关代码。
//再次申明的是CCLocationManager是不支持KVO来监听位置变化的,这里只是一个假设支持的话的使用方法。@interface AppDelegate@property(nonatomic, strong) CLLocationManager *locationManager;
@end@implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {self.locationManager = [CLLocationManager new];[self.locationManager startUpdatingLocation]; //开始监听位置变化return YES;
}
@end//第一个页面
@implementation VC1-(void)viewWillAppear:(BOOL)animated
{[ [UIApplication sharedApplication].delegate.locationManager addObserver:self forKeyPath:@"location" options:NSKeyValueObservingOptionNew context:NULL];
}-(void)viewWillDisappear:(BOOL)animated
{[ [UIApplication sharedApplication].delegate.locationManager removeObserver:self forKeyPath:@"location" ];}- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context
{//这里处理位置变化时的逻辑。
}
@end//第二个页面
@implementation VC2-(void)viewWillAppear:(BOOL)animated
{[ [UIApplication sharedApplication].delegate.locationManager addObserver:self forKeyPath:@"location" options:NSKeyValueObservingOptionNew context:NULL];
}-(void)viewWillDisappear:(BOOL)animated
{[ [UIApplication sharedApplication].delegate.locationManager removeObserver:self forKeyPath:@"location" ];}- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context
{//这里处理位置变化时的逻辑。
}
@end//.. 其他页面
接下来分析一下在什么情况下使用KVO:
- 最显而易见的,当我这个数据更新可能会引起多个依赖该对象的对象更新时使用KVO
- 当某个对象,在对应流程之中会创建多个副本,而且在这个副本的状态会不断产生变化,当副本增多的情况下,我们就需要使用KVO机制来根据新的状态来处理。
下面是我们使用多副本且不使用KVO的相关流程
使用KVO+单例,KVO在这里的意义就是,通知这个单例属性状态已经被改变,进行对应的更新
Notification通知方式
KVO模式实现了一种对属性变化的通知观察机制。而且这种机制由系统来完成,缺点就是他只是对属性的变化进行观察,而不能对某些异步方法调用进行通知处理。而如果我们想要正真的实现观察者模式而不局限于属性呢?答案就是iOS的NSNotificationCenter。
但是这个模式对应的也存在一些缺点,就使用通知的代码较为松散,在一定程度上,不利于程序的解读。看前面的内容,通过Delegate或者block时来设计业务层方法的回调时,可以很清楚的知道业务调用方法和实现机制的上下文,因为这些东西在代码定义里面就已经固化了,我们必须额外的去学习和了解哪些业务层的方法需要添加观察者哪些不需要,而且代码中不管在什么时候需要都要在初始化时添加一段代码上去。通知处理逻辑的可读写性以及代码的可读性也比较差。
总结
其实这篇文章写着写着,和前面写的五大传值方法其实有些重合,主要就是当时在学习传值技巧的时候还没有学到MVC架构,之前的学习还是停留在较为表面的,通过这次学习加深了对传值和MVC架构结合的理解
参考文章
论MVVM伪框架结构和MVC中M的实现机制
控制层的设计方法
模型层设计方法
相关文章:
「iOS」通过CoreLocation Framework深入了解MVC架构
「iOS」通过CoreLocation Framework重新了解多界面传值以及MVC架构 文章目录 「iOS」通过CoreLocation Framework重新了解多界面传值以及MVC架构前言CoreLocation了解根据需求建模设计属性方法设计协议传值Block传值KVONotification通知方式 总结参考文章 前言 在这个学期的前…...
spring实例化对象的几种方式(使用XML配置文件)
前言 Spring框架作为一个轻量级的控制反转(IoC)容器,为开发者提供了多种对象实例化的策略。通过这些策略,开发者可以更加灵活地控制对象的生命周期和依赖关系。无论是通过XML配置、注解配置还是Java配置,Spring都能…...
pyhton 批量往PDF文件指定位置里面填写数据
pyhton 批量往PDF文件指定位置里面填写数据 import PyPDF2 from PyPDF2 import PdfReader, PdfWriterdef modify_pdf(input_pdf_path, output_pdf_path, page_number, x, y, text):reader PdfReader(input_pdf_path)writer PdfWriter()for page in reader.pages:writer.add_p…...
深度学习——激活函数、损失函数、优化器
深度学习——激活函数、损失函数、优化器 1、激活函数1.1、一些常见的激活函数1.1.1、sigmoid1.1.2、softmax1.1.3、tanh1.1.4、ReLU1.1.5、Leaky ReLU1.1.6、PReLU1.1.7、GeLU1.1.8、ELU 1.2、激活函数的特点1.2.1、非线性1.2.2、几乎处处可微1.2.3、计算简单1.2.4、非饱和性1…...
上拉模式下引脚电平与代码读取值的关系
在单片机系统中,引脚的输入模式设置对上拉模式下引脚电平及代码读取值有着关键影响。 当引脚被配置为上拉模式且无外部信号输入时,内部上拉电阻使引脚保持高电平。此时,代码读取该引脚的值为 1。例如在一个简单的电路中,仅设置了…...
UNIX简史
从1991年Linux出现至今,由于众多IT巨头以及技术社区的推动,Linux已经成为非常成熟、可用于各种关键领域的操作系统,适当了解其发展历史,对于理顺其技术流派、从而更好地学习和使用Linux具有重要意义。由于其基于UNIX系统二十多年的…...
python学opencv|读取图像(十三)BGR图像和HSV图像互相转换深入
【1】引言 前序学习过程中,我们偶然发现:如果原始图像是png格式,将其从BGR转向HSV,再从HSV转回BGR后,图像的效果要好于JPG格式。 文章链接为: python学opencv|读取图像(十二)BGR图…...
ElasticSearch 搜索、排序、分页功能
一、DSL 查询文档 ElasticSearch 的查询依然是基于 json 风格的 DSL 来实现的。 官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/8.15/query-dsl.html 1.1 DSL 查询分类 常见的查询类型包括: 查询所有:查询出所有数…...
MAC虚拟机上安装WDA环境
MAC虚拟机上安装WDA环境 一、MAC虚拟机切换root权限二、macOS上安装xcode若你的macOS系统可以在appstore下载安装若你安装的macOS系统版本太低,无法在appstore上安装xcode 三、macOS上安装WebDriverAgent四、使用xcode配置WDA安装到手机上高版本系统支持 一、MAC虚拟…...
KDD 2025预讲会:10位一作的论文分享与话题思辨|12月18日全天直播
点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 圆桌思辨:一作们的KDD 2025投稿经验分享与热点探讨 1. KDD 2025 与往年相比有哪些新变化?两次投稿周期的新规则有哪些影响? 2. 第一篇KDD的工作是如何成功被接收的࿱…...
Input system手游的控制
手游离不开触屏控制 新的inputsystem 实现过程 安装input system在projectsetting中的player的othersettings中active input handing设置both打开window的analysis的input debugger。在options中设置为simulate touch input from mouse or pen。 增强触摸控制的相关知识 启…...
在 Visual Studio Code 中编译、调试和执行 Makefile 工程 llama2.c
在 Visual Studio Code 中编译、调试和执行 Makefile 工程 llama2.c 1. Installing the extension (在 Visual Studio Code 中安装插件)1.1. Extensions for Visual Studio Code1.2. C/C1.2.1. Pre-requisites 1.3. Makefile Tools 2. Configuring your project (配置项目)2.1.…...
KMP 算法
这里写目录标题 KMP数组计算方式**问题描述****初始准备****逐步推导过程****Step 1: i 1,子串为 ab****Step 2: i 2,子串为 aba****Step 3: i 3,子串为 abab****Step 4: i 4,子串为 ababa****Step 5: i 5,子串为…...
计算机网络中的三大交换技术详解与实现
目录 计算机网络中的三大交换技术详解与实现1. 计算机网络中的交换技术概述1.1 交换技术的意义1.2 三大交换技术简介 2. 电路交换技术2.1 理论介绍2.2 Python实现及代码详解2.3 案例分析 3. 分组交换技术3.1 理论介绍3.2 Python实现及代码详解3.3 案例分析 4. 报文交换技术4.1 …...
echarts图表自定义配置(二)——代码封装
下图是初版,火山图的代码。可以看出,里面的变量,逻辑,函数存在冗余,基本上都是改了参数,同样的get和set,去刷新图表;对于往后继续开发十几二十个图表,会很麻烦。因此需要…...
Serdes技术与Xilinx GT概览
目录 一、前言 二、Serdes技术 2.1 芯片间信号传输 2.2 Serdes技术 三、 Xilinx GT 3.1 7系列器件GT 3.2 Ultrascale GT 3.3 Ultrascale GT 四、参考资料 一、前言 对于芯片间高速信号传输技术,不得不提serdes以及在Xilinx在此基础上的高速收发器GT系列&…...
WEB开发: Node.js路由之由浅入深(三)自动配置路由 - 全栈工程师入门
前面我们一起学习了Node.js路由的两个进阶, (1)WEB开发: Node.js路由之由浅入深(一) - 全栈工程师入门 (2)WEB开发: Node.js路由之由浅入深(二)…...
6-9 捕获 0 异常(1)
中断号的 处理是这样的。 1、 cpu 根据中断号 去中断向量表 去找 第几个 表。、 2、 而 中断向量表 的内容是 GDT 的选择子。 3、 由于使用是的 平坦模型,所以只需要 将具体的函数给到 中断向量表的 offset 字段就可以了。 接下来 就是 在 代码中定义 中断门的属…...
社区团购创新模式与新兴技术融合的深度探索:基于开源、AI 智能名片、2+1 链动模式与 S2B2C 商城小程序
摘要:本文聚焦于社区团购这一新兴零售业态,深入剖析其“线上预售,线下自提,以销定采,落地集配”的 16 字箴言所蕴含的商业逻辑。详细探讨在物流与信息流层面社区团购的独特优势,并在此基础上研究开源理念、…...
day45 198.打家劫舍 213.打家劫舍II 337.打家劫舍III
198.打家劫舍 相邻的房子不可以打劫,所以递推式需要考虑; 初始化也需要考虑,可以从两个方向入手 方向1:从后往前看,dp[i] dp[i-1] class Solution { public:int rob(vector<int>& nums) {if (nums.size(…...
SQL server学习02-使用T-SQL创建数据库
目录 一, 使用T-SQL创建数据库 1,数据库的存储结构 2,创建数据库的语法结构 1)使用T-SQL创建学生成绩管理数据库 二,使用T-SQL修改数据库 1,修改数据库的语法结构 1)修改学生成绩管理数…...
绘图方式集合
1. 流程图 1.1 PlantUML 代码绘制流程图 1.1.1 简介 1.1.2 网站 你可以使用以下网站来将 PlantUML 代码转换成可视化的流程图: PlantUML 官方网站 网站地址:https://plantuml.com/plantuml此网站提供了一个在线工具,可以直接输入 PlantUM…...
sqoop导入hdfs,hive
sqoop将mysql中的表导入到hdfs中 sqoop import \ > --connect jdbc:mysql://192.168.52.150/test \ > --username root \ > --password 123456 \ > --table emp \ > --delete-target-dir \ > --target-dir /sqoop_works/emp_1将数据导入hive中,首…...
C语言动态内存管理【进阶--5--】
文章目录 [toc] 动态内存管理一、作用即意义二、动态内存函数的介绍Ⅰ、malloc()函数、free()函数Ⅱ、calloc()函数Ⅲ、realloc()函数 三、常见的动态内存错误Ⅰ、对NULL指针的解引用操作Ⅱ、对动态开辟空间的越界访问Ⅲ、对非动态开辟的内存使用free释放Ⅳ、使用free释放动态开…...
Hadoop其四,片与块,MapReduce原理,Shuffle过程,Combiner
目录 一、关于片和块 二、MapReduce的原理 MapTask执行阶段 ReduceTask的执行流程: 三、Shuffle 过程 map端: reduce端: 环形缓冲区: 四、Combiner 【可有可无】 五、需要记忆的内容 一、关于片和块 假如我现在500M这样…...
引领未来的变革:15种前沿RAG技术及其应用探索
在现代人工智能领域,检索增强生成(RAG)技术逐渐成为推动各种应用的重要力量。这些技术通过结合信息检索与文本生成,能够更有效地处理和利用信息。本文将详细介绍15种前沿RAG技术及其具体应用实例,以帮助您更好地理解这…...
gradle在IDEA 中无法使用的启动守护线程的问题
最近打开一个比较早的项目,Gradle 配置没有问题,IDEA 打开Java项目却不能初始化守护线程,UI 上只能看到失败,看不到具体原因。 首先尝试了升级最新的gradle 版本8.11, 实际上这个版本在本地命令行都不能正常工作,没有…...
C++小白实习日记——Pollnet,Efvi,UDP,数据类型转换(上)
上周主要是熟悉了一下公司内部一些自定义结构体对应的数据类型,要求:读取文件,将文件中数据转化为定义的结构体中的数据类型,按照时间进行排序,用UDP发送数据;在另一台服务器上接收数据,按照定义…...
git安装教程(Git-2.38.1-64-bit)
目录 一、git下载 二、git安装 1.更改安装路径 2.安装组件 3.选择开始菜单文件夹 4.选择Git默认编辑器 5.决定初始化新项目(仓库)的主干名字 6.修改Git的环境变量 7.选择SSH执行文件 9.选择HTTPS后端传输 10.配置行尾符号转换 11.配置终端模…...
C# OpenCvSharp DNN 实现百度网盘AI大赛-表格检测第2名方案第三部分-表格方向识别
目录 说明 效果 模型 项目 编辑 代码 参考 下载 其他 说明 百度网盘AI大赛-表格检测的第2名方案。 该算法包含表格边界框检测、表格分割和表格方向识别三个部分,首先,ppyoloe-plus-x 对边界框进行预测,并对置信度较高的表格边界…...
selenium 验证码滑块对齐没有验证通过
描述: 最近使用seleniuim采集有滑块验证码的数据,遇到了移动滑块对齐后,还是无法通过验证,经过模拟真人多次移动、控制移动时间(避免过快)一番尝试后、最终通过模拟抖动得以解决 解决办法: 把yoffset的值改为-6~6的…...
【Neo4J】neo4j docker容器下的备份与恢复
文章目录 一. 官网说明1. 操作说明2. 注意事项 二. docker 容器化操作1. 导出(备份)停止容器执行备份 2. 导入(恢复)停止容器(如果未停止)执行导入 3. 启动容器 一. 官网说明 https://neo4j.com/docs/operations-manual/current/…...
Java实现雪花算法获取id
Java实现雪花算法获取id 在 Java 中实现雪花算法(Snowflake)时,通常会设计一个工具类来生成全局唯一的 ID。这个工具类可以封装雪花算法的逻辑,并提供简单的接口来生成 ID。 以下是一个完整的 Java 工具类实现雪花算法的例子&am…...
Leetcode1338:数组大小减半
题目描述: 给你一个整数数组 arr。你可以从中选出一个整数集合,并删除这些整数在数组中的每次出现。 返回 至少 能删除数组中的一半整数的整数集合的最小大小。 代码思路: 这个代码的目的是解决一个特定的问题:给定一个整数数…...
【系统思辨】分散注意
注意力在我们的日常生活和工作中扮演着至关重要的角色。注意力可以提高效率和准确性、减少错误和失误,提升学习效率,促进创造力。与此同时,各种各样的生活事件在分散我们的注意力,并且还有很多分散我们注意的手段,比如…...
微信小程序中 Echarts 的巧妙运用
一、引入 Echarts 的准备工作 在微信小程序中引入 Echarts 需要进行一系列的准备工作。首先,我们可以从 echarts 官网或 GitHub 上下载 echarts-for-weixin 项目。找到其中的 ec-canvas 文件夹,这个文件夹将是我们引入到微信小程序项目中的关键部分。 …...
opencv——图片矫正
图像矫正 图像矫正的原理是透视变换,下面来介绍一下透视变换的概念。 听名字有点熟,我们在图像旋转里接触过仿射变换,知道仿射变换是把一个二维坐标系转换到另一个二维坐标系的过程,转换过程坐标点的相对位置和属性不发生变换&a…...
Gate学习(7)引入体素源
一、从GitHub下载体素源模型源码 下载地址:BenAuer2021/Phantoms-for-Nuclear-Medicine-Imaging-Simulation:用于核医学成像应用的模型(闪烁显像、SPECT 和 PET) --- BenAuer2021/Phantoms-For-Nuclear-Medicine-Imaging-Simulat…...
腾讯微信Android面试题及参考答案(多张原理图)
Android 应用的启动流程如下: 当用户点击应用图标时,首先会通过 Launcher(桌面启动器)来响应这个操作。Launcher 本身也是一个 Android 应用,它运行在系统中,负责管理和显示桌面上的图标等信息。 系统会检查应用是否已经有进程存在。如果没有,就会通过 Zygote 进程来孵化…...
【Android】View的工作流程
View的工作流程 开始了解一下View的工作流程,就是measure、layout和draw。measure用来测量View的宽高,layout用来确定View的位置,draw则用来绘制View。这一讲我们来看看measure流程,measure流程分为View的measure流程和ViewGroup…...
Linux基础指令
使用 tab 键补全 我们敲的所有的 Linux 命令 , 都可以使用 tab 键来尝试补全 , 加快效率 . 使用 ctrl c 重新输入 如果命令或者目录敲错了 , 可以 ctrl c 取消当前的命令 . ls :列出当前目录中的文件和子目录 语法 : ls [ 选项 ] [ 目录或文…...
Gemini 2.0 Flash重磅发布:多模态AI大模型,赋能实时交互与智能助手新体验
点击访问 chatTools 免费体验GPT最新模型,包括o1推理模型、GPT4o、Claude、Gemini等模型! 在AI领域竞争日益激烈的今天,谷歌再次亮剑,推出了新一代至强AI大模型——Gemini 2.0 Flash。这款模型不仅具备强大的多模态输入输出能力&a…...
项目十二 杜甫作品问卷
【项目目标】 理解网格系统的原理。理解媒体查询的工作原理。【項目内容】 使用网格系统进行响应式网页设计。运用媒体查询对不同类型的设备应用不同的样式。【项目步骤】 Bootstrap 框架资源既可以直接从 CDN 服务商服务器中引入,也可以加入本地素材文件夹中给出的资…...
7_Sass Introspection 函数 --[CSS预处理]
Sass 的 Introspection 函数允许开发者检查和操作样式表的内部结构,包括选择器、属性、值等。这些函数提供了对编译过程中 Sass 文件内容的深入访问能力,使得更复杂的逻辑处理成为可能。以下是一些常用的 Sass Introspection 函数及其用法示例࿱…...
Qt:Q_GLOBAL_STATIC实现单例(附带单例使用和内存管理)
转载 https://blog.csdn.net/m0_71489826/article/details/142288179 前言 本文主要写Q_GLOBAL_STATIC实现单例以及单例的释放,网上很多教程只有单例的创建,但是并没有告诉我们单例的内存管理,这就很头疼。 正文 使用 Qt 的 Q_GLOBAL_STA…...
HTML/CSS总结
HTML 1.1 标题标签h 为了使网页更具有语义化,我们经常会在页面中用到标题标签,HTML提供了6个等级的标题,即 标题标签语义: 作为标题使用,并且依据重要性递减 其基本语法格式如下: <h1> 标题文本…...
字符串性能对比
效率(1) : String.indexOf与String.contains效率测试_string contains效率-CSDN博客 结论是前者效率高,源码里面conatins是使用indexof 在jdk8中contains直接调用的indexOf(其他版本没有验证),所以要说效率来说肯定是indexOf高,但contains也就多了一层方法栈,so 什…...
【漫话机器学习系列】005.神经网络的结构(architecture on the neural network)
神经网络(Neural Network)是一种模拟人脑神经系统的计算模型,由大量相互连接的神经元(节点)组成,广泛应用于深度学习和机器学习领域。以下是神经网络的基本结构及关键组成部分。 1. 神经网络的基本组成 一…...
关卡选择与布局器
unity布局管理器 使用unity布局管理器轻松对关卡选择进行布局。 实现过程 准备普通按钮button设置字体和对应的sprite设置父gameobject(levelbase) 再创建UI.image(selectbackground)布局背景和大小gameobject(grid…...
数据分析实战—房价特征关系
1.实战内容 (1) 读取房价特征关系表(house_price.npz)绘制离地铁站的距离与单位面积的房价的散点图,并对其进行分析; import pandas as pd import numpy as np import warnings warnings.filterwarnings(&…...