【iOS】—— 响应者链和事件传递链

news2024/11/17 1:58:05

响应者链和事件传递链

文章目录

  • 响应者链和事件传递链
      • 二者概念
      • 响应者
      • 响应链事件
      • UIKit继承图
        • UIResponder
        • UITouch
          • UITouch几个重要属性
        • UITouch的两个方法(可用于view的拖拽)
      • UIEvent
        • UIEvent几个重要属性
    • 事件的产生与传递
      • 传递链
        • 传递过程
        • hitTest:withEvent:方法的可能实现
      • 响应链
        • 响应过程
        • 完整的触摸过程
          • 完整的触摸过程如何实现
        • 举例
        • iOS的响应者链的传递过程和触摸事件的传递过程一样吗
        • 响应规则定义区别
        • 过程区别
    • 总结

二者概念

响应链

  • 由离用户最近的view向系统传递。
  • initial view –> super view –> …… –> view controller –> window –> Application –> AppDelegate

传递链

  • 由系统向离用户最近的view传递。
  • UIKit –> active app's event queue –> window –> root view –> …… –> lowest view

请添加图片描述

响应者

响应者链中的各个对象被称为“响应者”(responder),响应者链的根节点是UIApplication对象,所有的事件都从UIApplication对象开始传递。当事件发生时,UIApplication对象首先将其传递给当前显示在屏幕上的UIWindow对象,然后递归地向下传递给其子视图,依次传递给UIViewControllerUIView等响应者对象进行处理,直到事件被处理完毕或被丢弃。

在响应者链中,每个响应者对象都可以处理事件,也可以选择将事件传递给下一个响应者对象进行处理,或者直接丢弃事件。响应者链中的每个响应者对象都可以重写几个方法来处理事件,这些方法包括touchesBegan:withEvent:touchesMoved:withEvent:touchesEnded:withEvent:等等。

响应链事件

请添加图片描述
iOS中的事件类型:

  • 触摸事件(手机在屏幕上触摸)
  • 加速计事件(手机摇一摇)
  • 远程遥控事件(遥控器控制)

UIKit继承图

请添加图片描述

通过继承图我们能知道,我们平时在使用的UI大多数都是继承自UIResponder的,只有继承自UIResponder的对象才能接收并处理事件,我们把这类对象称为“响应者”。就像UIApplication,UIViewController,UIView都继承自UIResponder,因此他们都可以接收处理事件。

UIResponder

UIResponder中提供了三种处理事件的方法(触摸事件、加速计事件、远程控制事件),所以我们才能在UI中实现各种点击事件:

// 触摸事件
// 开始接触屏幕,就会调用一次
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
// 手指开始移动就会调用(这个方法会频繁的调用,其实一接触屏幕就会多次调用)
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
// 手指离开屏幕时,调用一次
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
// 触摸结束前,某个系统事件(例如电话呼入)会打断触摸过程,或者view上面添加手势时,系统会自动调用view的下面方法
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

// 加速计事件
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;

// 远程控制事件
- (void)remoteControlReceivedWithEvent:(UIEvent *)event;

通过这三种处理事件的方法就可以知道事件的整个过程,我们平时经常使用的就是触摸事件,其中有两个参数,UITouch和UIEvent。

UITouch

当你用一根手指触摸屏幕时,会创建一个与之关联的UITouch对象,一个UITouch对象对应一根手指。在事件中可以根据NSSet中UITouch对象的数量得出此次触摸事件是单指触摸还是双指多指等等。

UITouch几个重要属性
// 触摸产生时所处的窗口
@property(nonatomic, readonly, retain) UIWindow *window;
// 触摸产生时所处的视图
@property(nonatomic, readonly, retain) UIView *view;
// 短时间内点按屏幕的次数,可以根据tapCount判断单击、双击或更多的点击
@property(nonatomic, readonly) NSUInteger tapCount;
// 记录了触摸事件产生或变化时的时间,单位是秒
@property(nonatomic, readonly) NSTimeInterval timestamp;
// 当前触摸事件所处的状态
@property(nonatomic, readonly) UITouchPhase phase;

UITouch的两个方法(可用于view的拖拽)

- (CGPoint)locationInView:(UIView *)view;
/*
  返回值表示触摸在view上的位置
  这里返回的位置是针对传入的view的坐标系(以view的左上角为原点(0, 0))
  调用时传入的view参数为nil的话,返回的是触摸点在UIWindow的位置
*/

// 该方法记录了前一个触摸点的位置
- (CGPoint)previousLocationInView:(UIView *)view;

UIEvent

每产生一个事件,就会产生一个UIEvent事件,UIEvent称为事件对象,记录事件产生的时刻和类型等等。

UIEvent几个重要属性

// 事件类型
@property(nonatomic, readonly) UIEventType type;
@property(nonatomic, readonly) UIEventSubtype subtype;
// 事件产生的时间
@property(nonatomic, readonly) NSTimeInterval timestamp;

事件的产生与传递

传递链

UIApplication传递事件到当前Window是明确的(即一定会的),接下来就是从Window开始找最佳响应视图,此过程有两个重要的方法:

- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event; // 递归调用的事件,从最底层开始,一直往上找,直到找到一个最上层的能响应的视图就返回该视图
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event; // 判断点击区域是否在该视图的范围中,不在该视图范围中就结束递归,返回nil

传递过程

  • 1.发生触摸事件后,压力转为电信号,系统将产生UIEvent事件,记录事件产生的时间和类型。
  • 2.系统会将该事件添加到UIApplication管理的事件队列中。
  • 3.UIApplication将事件队列中的第一个事件分发给UIWindow,这时就会调用UIWindow的hitTest:withEvent:方法。
  • 4.当前 window/视图 调用hitTest:withEvent:方法,hitTest:withEvent:方法内部会通过以下条件判断 window/视图 能否能响应事件,以下判断条件都是不能响应事件的:
    • 不允许交互:userInteractionEnabled=NO
    • 隐藏:hidden = YES
    • 透明度:alpha < 0.01,alpha小于0.01为全透明
  • 5.如果能响应,该函数又会调用pointInside方法判断当前触摸点是不是在视图范围内,不在视图范围内也是不会响应的。
  • 6.如果在 window/视图 范围内,开始反向遍历 window/视图 的子视图列表subviews,遍历的同时会调用subviews中每个子视图的hitTest:withEvent:方法,判断逻辑和上面的一样,直到找到离用户最近的、能响应事件的视图。
  • 4.5.6过程会递归判断,直到找到最外层合适的view,最后返回的view就是最佳响应视图。

hitTest:withEvent:方法的可能实现

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    // 1.判断当前控件能否接收事件
    if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha) return nil;     
    // 2. 判断点在不在当前控件
    if ([self pointInside:point withEvent:event] == NO) return nil;
    // 3.从后往前遍历自己的子控件
    NSInteger count = self.subviews.count;
    for (NSInteger i = count - 1; i >= 0; i--) {
        UIView *childView = self.subviews[i];
        // 把当前控件上的坐标系转换成子控件上的坐标系
        CGPoint childP = [self convertPoint:point toView:childView];
        UIView *fitView = [childView hitTest:childP withEvent:event];
        if (fitView) { // 直到寻找到最合适的view
            return fitView;
        }
    }
    // 循环结束,表示没有比自己更合适的view
    return self;
}
  • 查找结束,返回最终的view,UIApplication会调用UIWindow的sendEvent,从而触发对应的响应方法,如果我们在UIWindow中重写sendEvent而不调用super的实现,所有的点击事件都不会触发,因为事件是从最底层传递上来的,你切断了最底层的传递,肯定就无法响应了
  • 实际调用hitTest的过程,系统为了找到精准的触摸点会多次调用hitTest方法
  • 如果重写hitTest返回self,传递过程就会终止,那么当前view就是最合适的view;返回nil,传递也会终止,父视图superView就是最合适的view
  • 如果遍历subviews的过程都没找到合适的view,那么subviews中的子view的hitTest方法都会被调用一次
  • hitTest方法会调用pointInside判断当前视图是否在点击区域,所以超出父视图边界的控件无法响应事件
  • 同一个view上的两个子视图有重叠部分,后加入的视图会被加入到事件传递链
  • 在打印视图层级结构中部分视图执行hitTestpointInSide方法中可以看到,viewController并没有执行这两个方法。所以传递链中没有viewController,因为viewController本身不具有大小的概念。而响应链中有viewController,因为viewController继承UIResponder。

响应链

当找到最合适的响应者之后,便会调用控件相应的touch方法来作具体处理,然而这些方法默认都是不做处理的,但是我们要是想让该响应者响应该事件就可以重写一开始说的那几个响应事件方法,并且我们也可以在重写touch方法中加入[super touch],使多个响应者同时响应同一事件。如果我们对响应事件的方法不做处理那么将该事件随着响应者链条往回传递,交给上一个响应者来处理(即调用super的touch方法),直到找到一个能响应该事件的响应者。

响应过程

  • 1.通过hitTest返回的view为当前事件的第一响应者,nextResponder为上一个响应者
  • 2.如果当前view默认不去重写响应事件方法,或者重写调用了父类的响应事件方法,响应就会沿着响应者链向上传递(上一个响应者一般是superView,可以通过nextResponder属性获取上一个响应者)
  • 3.如果上一个响应者是viewController,由viewController的view处理,如果view本身没处理,则传递给viewController本身
  • 4.重复上述过程,直到传递到window,window如果也不能处理,则传递到UIApplication,如果UIApplication的delegate继承自UIResponder,则交给delegate处理,如果delegate也不处理最后丢弃

完整的触摸过程

一次完整的触摸过程,会经历 3 个状态。 上面说了完整的响应事件有如下四个事件:

触摸开始:- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
触摸移动:- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
触摸结束:- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
触摸取消(可能会经历):- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
完整的触摸过程如何实现

一个完整的触摸事件流程通常包括以下几个步骤:

  • 手指触摸到屏幕,系统会创建一个与手指相关联的 UITouch 对象,并将其加入到系统中的事件队列中。
    系统会将该事件发送给当前 UIWindow 对象,即调用 UIWindow 对象的 touchesBegan(_:with:) 方法,并将该事件传递给子视图。
  • 从根视图开始,系统会通过递归调用 hitTest(_:with:) 方法,寻找响应该事件的视图。在每个视图中,系统都会调用point(inside:with:) 方法,判断该视图是否包含该事件的触摸点。
  • 一旦找到了响应该事件的视图,系统会将该事件发送给该视图,即调用该视图的touchesBegan(:with:)方法。
    在该视图的 touchesBegan(:with:) 方法中,开发者可以对该事件做出相应的处理,比如更改视图的状态、更新视图的内容等。
  • 如果该事件需要传递给其它视图进行处理,开发者可以手动调用 next 方法,将该事件传递给下一个响应者。
  • 当手指离开屏幕时,系统会将一个 touch 对象的 phase 属性设置为 .ended,并将该 touch 对象从事件队列中移除。
    当前的 UIWindow 对象会将该事件发送给响应者链中的下一个响应者。如果没有下一个响应者,则该事件的响应过程结束。

举例

  • 4 个触摸事件处理方法中,都有 NSSet *touches 和 UIEvent *event 两个参数。
  • 一次完整的触摸过程中,只会产生一个事件对象,4 个触摸方法都是同一个 event 参数。
  • 如果两根手指同时触摸一个 view,那么 view 只会调用一次 touchesBegan:withEvent: 方法,touches 参数中装着 2 个 UITouch 对象。
  • 如果这两根手指一前一后分开触摸同一个 view,那么 view 会分别调用 2 次 touchesBegan:withEvent: 方法,并且每次调用时的 touches 参数中只包含一个 UITouch 对象。
  • 根据 touches 中 UITouch 的个数可以判断出是单点触摸还是多点触,判断多少次点击:UITouch 的属性 @property(nonatomic,readonly) NSUInteger tapCount;
  • 事件的产生和传递:
    • 发生触摸事件后,系统会将该事件加入到一个由 UIApplication 管理的事件队列中;
    • UIApplication 会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常先发送事件给应用程序的主窗口(keyWindow);
    • 主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,但是这仅仅是整个事件处理过程的第一步;
    • 找到合适的视图控件后,就会调用视图控件的 touches 方法来作具体的事件处理
      请添加图片描述
      UIView 不接收触摸事件的三种情况:
  • 不接收用户交互userInteractionEnabled = NO;
  • 隐藏 hidden = YES;
  • 透明 alpha = 0.0 ~ 0.01。
    UIImageView 的 userInteractionEnabled 默认就是 NO,因此 UIImageView 以及它的子控件默认是不能接收触摸事件的。

iOS的响应者链的传递过程和触摸事件的传递过程一样吗

先触发响应者事件,接着触发触摸事件,也就是先寻找命中者.
实际上,触摸事件的传递确实是从父控件到子控件,而响应者链的传递是从子控件到父控件,两者的传递方向是相反的

下面是触摸事件的传递过程:

  • 用户触摸屏幕,系统将创建一个 UITouch 对象,并将其加入到一个 UIEvent 对象中。
  • UIEvent 对象传递给 UIApplication 对象,由 UIApplication 对象将事件分派给应用程序的 UIWindow
  • UIWindow 对象将事件分派给合适的视图控制器的视图层次结构。事件会从根视图开始沿着视图层次结构向下传递,直到找到合适的视图来响应事件。
  • 视图响应事件,并将事件传递给其父视图,直到事件到达视图层次结构的最上层视图。
  • 如果事件没有被任何视图对象处理,则系统将发送一个 cancel 事件,表示触摸事件已被取消。

而响应者链的传递过程则是从子控件到父控件,如下:

  • 视图层次结构中的子控件可以成为响应者对象,当用户与子控件交互时,该控件将成为响应者对象。
  • 当响应者对象无法处理事件时,它将将事件发送给其父控件,并在响应者链中继续向上传递。
  • 如果父控件也无法处理事件,则将事件发送到祖先控件,直到到达视图层次结构中的最上层控件。
  • 如果没有控件能够处理事件,则事件将被丢弃。

响应规则定义区别

先触发响应者事件,接着触发触摸事件
触摸事件传递过程是从父控件到子控件,即由UIApplication将事件发送到最顶层的控件,然后由这个控件向下逐级传递事件,直到找到最合适的处理者为止。在传递过程中,如果一个控件能够响应事件,那么就会处理事件并结束传递;如果不能响应事件,那么就会将事件传递给下一个响应者。

而响应者链的传递过程则是从子控件到父控件。当一个控件接收到事件后,它首先会将事件交给自己的响应者对象处理,然后再交给它的父控件的响应者对象处理,直到到达最顶层的响应者对象为止。在传递过程中,如果一个响应者对象能够响应事件,那么就会处理事件并结束传递;如果不能响应事件,那么就会将事件传递给它的父响应者对象。

因此,虽然两个传递过程都涉及到父子控件之间的传递,但它们的传递顺序和目的不同。触摸事件传递过程主要是为了找到最合适的控件来处理事件,而响应者链传递过程则是为了让控件的父子关系中的响应者对象能够逐级处理事件。

过程区别

响应者链的事件传递过程:

  • 如果 view 的控制器存在,就传递给控制器;如果控制器不存在,则将其传递给它的父视图;
  • 在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给 window 对象进行处理;
  • 如果 window 对象也不处理,则其将事件或消息传递给 UIApplication 对象;
  • 如果 UIApplication 也不能处理该事件或消息,则将其丢弃。

触摸事件处理的详细过程:

  • 用户点击屏幕后产生的一个触摸事件,经过一系列的传递过程后,会找到最合适的视图控件来处理这个事件;
  • 找到最合适的视图控件后,就会调用控件的 touches 方法来作具体的事件处理;
  • 这些 touches 方法的默认做法是将事件顺着响应者链条向上传递,将事件交给上一个响应者进行处理。响应者链条就是由多个响应者对象连接起来的链条,能很清楚地看见每个响应者之间的关系,并且可以让一个事件多个对象处理;

如何判断上一个响应者:

  • 如果当前这个 view 是控制器的 view,那么控制器就是上一个响应者;
  • 如果当前这个 view 不是控制器的 view,那么父控件就是上一个响应者。

事件传递的完整过程:

  • 先将事件对象由上往下传递(由父控件传递给子控件),找到最合适的控件来处理这个事件;
  • 调用最合适控件的 touches…. 方法;
  • 如果调用 [super touches….] 就会将事件顺着响应者链条往上传递,传递给上一个响应者;
  • 接着就会调用上一个响应者的 touches…. 方法。

总结

iOS的响应者链机制的步骤是先通过hitTest和PointSide方法找到合适的控件-Initial View如果这个响应者能够响应
则进行

Initial View -> View Controller(如果存在) -> superview -> · ··  -> rootView -> UIWindow -> UIApplication

如果一个View有一个视图控制器(View Controller),它的下一个响应者是这个视图控制器,紧接着才是它的父视图(Super View),如果一直到Root View都没有处理这个事件,事件会传递到UIWindow(iOS中有一个单例Window),此时Window如果也没有处理事件,便进入UIApplication,UIApplication是一个响应者链的终点,它的下一个响应者指向nil,以结束整个循环。

这块内容不算难,也比较好理解,但是好多博客都没有讲清楚主要问题,推荐看我疼组的博客:我是道哥

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多路归并排序

内部排序和外部排序 内部排序&#xff1a;整个的排序过程都在内存中进行排序 外部排序&#xff1a;对大文件进行排序&#xff0c;无法将整个需要排序的文件复制到内存&#xff0c;所以会把文件存储到外村&#xff0c;等排序时再把数据一部分一部分地调入内存进行排序&#xff…

Java基础一(String)

Java基础一(String) 概览&#xff1a; String 被声明为 final&#xff0c;因此它不可被继承。(Integer 等包装类也不能被继承&#xff09; 在 Java 8 中&#xff0c;String 内部使用 char 数组存储数据。 public final class Stringimplements java.io.Serializable, Compa…

盘点并发编程的12种业务场景,面试别再说你不会并发了

前言 并发编程是一项非常重要的技术&#xff0c;无论在面试&#xff0c;还是工作中出现的频率非常高。 并发编程说白了就是多线程编程&#xff0c;但多线程一定比单线程效率更高&#xff1f; 答&#xff1a;不一定&#xff0c;要看具体业务场景。 毕竟如果使用了多线程&…

【MFC】网络通信(23)

Windows Sockets 规范是 Windows 平台下定义的可以兼容二进制数据传输的网络编程接口&#xff0c;是基于伯克利加利福尼亚大学的 BSD UNIX Sockets 的实现。 Socket 套接字分为两种类型&#xff1a;数据报 socket 和数据流 socket。 数据报套接字&#xff0c;即无连接套接字&…

网络通信基础 - 多路复用技术(频分多路复用、时分多路复用、波分多路复用)

文章目录 1 概述1.1 复用器 MUX 2 分类2.1 频分多路复用 FDM2.2 时分多路复用 TDM2.3 波分多路复用 WDM 1 概述 1.1 复用器 MUX 多路复用技术&#xff1a;把多个低速信道组合成一个高速信道的技术这种技术要用到两个设备&#xff0c;统称为 多路器&#xff08;MUX&#xff09…

Chapter13-基于 Netty 的通信实现

13.l Netty 介绍 Netty 是一个网络应用框架&#xff0c;或者说是一个 Java 网络开发库。 Netty 提供异步事件驱动的方式&#xff0c;使用它可以快速地开发出高性能的网络应用程序&#xff0c;比如客户端&#xff0f;服务器自定义协议程序&#xff0c;大大简化了网络程序的开发过…

ParticleSystem中的Culling Mode对耗时有怎样的影响

1&#xff09;ParticleSystem中的Culling Mode对耗时有怎样的影响 ​2&#xff09;关于API&#xff0c;OpenGL和Vulkan的疑问 3&#xff09;SVC分别搜集Keyword&#xff0c;多次搜集与单独搜集Warmup内存比较 4&#xff09;Occlusion Culling能否降低Culling耗时 这是第332篇UW…

kaggle酶稳定性预测第三名解决方案分享

最近在kaggle参加了诺维信举办的酶稳定性预测比赛 &#xff0c;最终很幸运获得了第三名&#xff0c;这篇文章主要是简单介绍一下解决方案&#xff0c;具体的数据和题目要求可访问上面的链接。 文章目录 模型概述特征工程模型XGB1XGB2XGB3 EnsembleNESP 3D geometryFoldXThermo…

AI即将夺走程序员的工作?实操验证

随着ChatGPT的普及&#xff0c;许多媒体开始报道“AI即将夺走程序员的工作”、“AI来了&#xff01;各大长都开始大幅度裁员”&#xff0c;这让一些初级码农感到担忧&#xff0c;而一些高级程序员则表示不屑一顾。这到底是不是“狼来了”。今天&#xff0c;我们将进行实际测试来…

实例了解GOT,PLT和动态链接

深入了解GOT,PLT和动态链接 我们使用一个简单的例子来了解动态链接库的链接过程&#xff0c;以及在这个过程中使用到的GOT和PLT的作用是什么。 文件准备 代码结构如下所示&#xff1a; [rootlocalhost test]# tree . . ├── main.c └── symbol.csymbol.c的内容如下&am…

聊聊布隆过滤器

目录 一、什么是布隆过滤器&#xff1f; 二、使用场景 三、原理 四、使用 4.1、Guava实现 4.2、Redisson实现 一、什么是布隆过滤器&#xff1f; 布隆过滤器&#xff08;英语&#xff1a;Bloom Filter&#xff09;是1970年由布隆提出的&#xff0c;是一种数据结构。它实际…

推式配货(Push)、拉式配货(Pull)和配送需求计划(DRP)的区别

随着电子商务的迅猛发展&#xff0c;物流配送服务已然成为企业竞争最为核心的环节&#xff0c;一个全面、完善的物流配送方案&#xff0c;能够帮助企业满足客户交期、节约运输和库存成本&#xff0c;促进各环节沟通&#xff0c;提高生产稳定性。同时&#xff0c;物流配送的许多…

如何在Java中高效地实现数字的反转和字符串的拼接?

给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都不会以 0 …

2023爱分析·工业互联网解决方案-设备后市场服务市场厂商评估报告

01 研究范围定义 “十四五”期间工信部等发布《“十四五”智能制造发展规划》&#xff0c;强调智能制造是我国制造强国主攻方向&#xff0c;加快推动智能制造发展&#xff0c;深化智能推广应用&#xff0c;开拓制造业数字化转型升级新路径&#xff0c;智能制造市场发展潜力进…

Pyqt应用相关之与Excel的联接

利用所学相关Pyqt实现对于Excel文件内部数据的处理&#xff0c;首先需要获取Excel的数据&#xff0c;在获取后进行保存处理即可完成相应的操作。 def save_data_btn_click(self):dir self.save_dir_text.text().strip()self.data_frame_group.to_excel(dir output.xlsx,sheet…

IMX6ULLPRO交叉编译第一个APP和第一个led驱动

目录 配置交叉编译工具链 永久生效 测试交叉编译工具链 第一个交叉编译程序 开发板运行 LED第一个驱动 开发板下操作 执行测试程序 配置交叉编译工具链 交叉编译工具链用来在 Ubuntu 主机上编译应用程序&#xff0c;而这些应用程序是在 ARM 等其他平台上运行…

GPT对SaaS领域有什么影响?

GPT火了&#xff0c;Chat GPT真的火了。 突然之间&#xff0c;所有人都在讨论AI&#xff0c;最初的访客是程序员、工程师、AI从业者&#xff0c;从早高峰写字楼电梯里讨论声&#xff0c;到村里大爷们的饭后谈资&#xff0c;路过的狗子都要和它讨论两句GPT的程度。 革命的前夜…

图像配准(匹配)与变化检测

文章目录 简介A Survey on Deep Learning-Based Change Detection from High-Resolution Remote Sensing Images 2022变化检测的基本框架基于神经网络的变化检测特征抽取变化检测的粒度场景级的变化检测&#xff08;SLCD&#xff09;目标级别的变化检测 Deep Learning-Based Ch…

全志v851s uart3 设置成普通串口收发

本文转载自&#xff1a;https://bbs.aw-ol.com/topic/3281/ 由于UART0 被设定为系统dubug 输出&#xff08;简单来说就是将ttyS0 设定为console&#xff09;&#xff0c;所以使用UART3 作为普通的串口&#xff0c;进行与别的设备通信。 1. 查看硬件电路图SCH_Schematic1_2022…