【iOS】事件传递与响应机制

文章目录

  • 前言
  • 事件UIEvent
  • 一、事件传递
    • 遍历顺序
  • 二、手势识别
  • 三、响应机制
      • UIResponder(响应者)
      • 响应者链
  • 四、相关应用
    • 扩大button点击范围
    • 穿透事件
  • 总结


前言

提到响应者链与事件传递,如果看过其他人的博客,经常能看到这经典的三张图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文会对事件的传递与响应机制进行详细的讲解

事件UIEvent

在开讲之前,我们先来理解一下UIEvent
事件指的是 UIEvent : NSObject,它的API文档很简单:

typedef NS_ENUM(NSInteger, UIEventType) {UIEventTypeTouches,UIEventTypeMotion,UIEventTypeRemoteControl,UIEventTypePresses API_AVAILABLE(ios(9.0)),UIEventTypeScroll      API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos) = 10,UIEventTypeHover       API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos) = 11,UIEventTypeTransform   API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos) = 14,
};typedef NS_ENUM(NSInteger, UIEventSubtype) {// available in iPhone OS 3.0UIEventSubtypeNone                              = 0,// for UIEventTypeMotion, available in iPhone OS 3.0UIEventSubtypeMotionShake                       = 1,// for UIEventTypeRemoteControl, available in iOS 4.0UIEventSubtypeRemoteControlPlay                 = 100,UIEventSubtypeRemoteControlPause                = 101,UIEventSubtypeRemoteControlStop                 = 102,UIEventSubtypeRemoteControlTogglePlayPause      = 103,UIEventSubtypeRemoteControlNextTrack            = 104,UIEventSubtypeRemoteControlPreviousTrack        = 105,UIEventSubtypeRemoteControlBeginSeekingBackward = 106,UIEventSubtypeRemoteControlEndSeekingBackward   = 107,UIEventSubtypeRemoteControlBeginSeekingForward  = 108,UIEventSubtypeRemoteControlEndSeekingForward    = 109,
};/// Set of buttons pressed for the current event
/// Raw format of: 1 << (buttonNumber - 1)
/// UIEventButtonMaskPrimary = 1 << 0
typedef NS_OPTIONS(NSInteger, UIEventButtonMask) {UIEventButtonMaskPrimary    = 1 << 0,UIEventButtonMaskSecondary  = 1 << 1
} NS_SWIFT_NAME(UIEvent.ButtonMask) API_AVAILABLE(ios(13.4)) API_UNAVAILABLE(tvos, watchos);/// Convenience initializer for a button mask where `buttonNumber` is a one-based index of the button on the input device
/// .button(1) == .primary
/// .button(2) == .secondary
UIKIT_EXTERN UIEventButtonMask UIEventButtonMaskForButtonNumber(NSInteger buttonNumber) NS_SWIFT_NAME(UIEventButtonMask.button(_:)) API_AVAILABLE(ios(13.4)) API_UNAVAILABLE(tvos, watchos);UIKIT_EXTERN API_AVAILABLE(ios(2.0)) @interface UIEvent : NSObject@property(nonatomic,readonly) UIEventType     type API_AVAILABLE(ios(3.0));
@property(nonatomic,readonly) UIEventSubtype  subtype API_AVAILABLE(ios(3.0));@property(nonatomic,readonly) NSTimeInterval  timestamp;@property (nonatomic, readonly) UIKeyModifierFlags modifierFlags API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos);
@property (nonatomic, readonly) UIEventButtonMask buttonMask API_AVAILABLE(ios(13.4)) API_UNAVAILABLE(tvos, watchos);@property(nonatomic, readonly, nullable) NSSet <UITouch *> *allTouches;
- (nullable NSSet <UITouch *> *)touchesForWindow:(UIWindow *)window;
- (nullable NSSet <UITouch *> *)touchesForView:(UIView *)view;
- (nullable NSSet <UITouch *> *)touchesForGestureRecognizer:(UIGestureRecognizer *)gesture API_AVAILABLE(ios(3.2));// An array of auxiliary UITouch’s for the touch events that did not get delivered for a given main touch. This also includes an auxiliary version of the main touch itself.
- (nullable NSArray <UITouch *> *)coalescedTouchesForTouch:(UITouch *)touch API_AVAILABLE(ios(9.0));// An array of auxiliary UITouch’s for touch events that are predicted to occur for a given main touch. These predictions may not exactly match the real behavior of the touch as it moves, so they should be interpreted as an estimate.
- (nullable NSArray <UITouch *> *)predictedTouchesForTouch:(UITouch *)touch API_AVAILABLE(ios(9.0));@endNS_ASSUME_NONNULL_END#else
#import <UIKitCore/UIEvent.h>
#endif

我们以 UIEventType 作为突破口

typedef NS_ENUM(NSInteger, UIEventType) {UIEventTypeTouches,UIEventTypeMotion,UIEventTypeRemoteControl,UIEventTypePresses API_AVAILABLE(ios(9.0)),UIEventTypeScroll      API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos) = 10,UIEventTypeHover       API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos) = 11,UIEventTypeTransform   API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos) = 14,
};

目前iOS主流使用的事件有三种

  • touch events(触摸事件)
  • motion events(运动事件)
  • remote-control events(远程控制事件)
    在这里插入图片描述

我们这里着重讲一下触摸事件

触摸事件就是我们的手指或者苹果的
Pencil(触笔)在屏幕中所引发的互动,比如轻点、长按、滑动等操作,是我们最常接触到的事件类型。触摸事件对象可以包含一个或多个触摸,并且每个触摸由
UITouch 对象表示。当触摸事件发生时,系统会将其沿着线路传递,找到适当的响应者并调用适当的方法,例如
touchedBegan:withEvent:。响应者对象会根据触摸来确定适当的方法。 触摸事件分为以下几类:

手势事件

  • 长按手势(UILongPressGestureRecognizer)
  • 拖动手势(UIPanGestureRecognizer)
  • 捏合手势(UIPinchGestureRecognizer)
  • 响应屏幕边缘手势(UIScreenEdgePanGestureRecognizer)
  • 轻扫手势(UISwipeGestureRecognizer)
  • 旋转手势(UIRotationGestureRecognizer)
  • 点击手势(UITapGestureRecognizer)
  • 自定义手势
  • 点击 button 相关

触摸事件对应的对象为 UITouch,UITouch实际上就对应着我们的手指,有几根手指就有几个UITouch对象

一、事件传递

事件传递机制(Event Handling)
iOS的事件传递系统将触摸和其他事件(如动作、手势)发送到视图层次结构中的适当对象。在事件传递过程中,系统通常从根视图开始查找,并递归向下查找以找到最适合处理该事件的视图。

传递流程

  • 事件的产生
    用户通过手势或是触摸等其他操作与设备交互,生成事件,系统将事件传递给应用的UIApplication实例,以开始事件分发
  • UIApplication事件分发
    UIApplication负责顶层管理所有用户输入事件。
    它将事件传递给当前活动的UIWindow对象,以进一步查找适合的响应者。
  • UIWindow事件分发
    当前活动的UIWindow对象接收事件并通过hitTest:withEvent:方法开始寻找适当的视图
    UIWindow遍历整个视图层次结构,以找到最合适的视图来响应事件。
  • 命中测试(Hit-Testing)
    hitTest:withEvent:寻找第一响应者的核心方法。它通过以下步骤工作:
  1. 检查当前视图的userInteractionEnabled、hiddenalpha属性以确保视图可交互。当视图隐藏属性hidden=NO、交互userInteractionEnabled=YES、透明度alpha>0.01三者同时满足才拥有响应能力。
  2. 调用pointInside:withEvent:,确定触摸点是否在当前视图的边界范围内。
  3. 从后往前遍历子视图,递归调用子视图的hitTest:withEvent:方法。
  4. 如果找到合适的子视图,它将返回该子视图作为第一响应者;否则返回当前视图自身。

我们可以写一个其简单实现实例

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {// 视图不能交互、隐藏或不可见时,直接返回nilif (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha < 0.01) {return nil;}// 判断触摸点是否在当前视图范围内if (![self pointInside:point withEvent:event]) {return nil;}// 从后往前遍历子视图(子视图叠加次序),递归调用for (UIView *subview in [self.subviews reverseObjectEnumerator]) {// 转换坐标到子视图的坐标系CGPoint convertedPoint = [subview convertPoint:point fromView:self];// 递归查找子视图UIView *hitView = [subview hitTest:convertedPoint withEvent:event];if (hitView != nil) {return hitView;}}// 没有合适的子视图时,当前视图自己成为第一响应者return self;
}
  • 第一响应者确定
    如果确定了当前触摸点在当前视图上,同时当前视图没有任何子视图,那么当前视图就成为第一响应者并开始处理触摸事件
    touchesBegan:withEvent:、touchesMoved:withEvent:、touchesEnded:withEvent:、touchesCancelled:withEvent:方法由第一响应者接收并处理,这些都是触摸事件

讲到这里,其实我们的事件传递就已经结束了,事件传递的目的就是为了让我们找到第一响应者

总结一下第一响应者

  1. 能够响应触摸事件
  2. 触摸点在自己身上
  3. 没有任何子视图,或是所有子视图都不在触摸点上

在这里插入图片描述

遍历顺序

我们在上图中看到了在subViews中查找响应者的过程是倒序遍历,这是什么意思呢

也就是我们遍历当前视图的子视图时,首先hitTest:withEvent:方法会被子视图数组中的最后一个元素调用

如何理解这句话呢?简单理解就是会从最后一个添加到当前视图的子视图进行遍历,也就是视图上最上层的子视图是第一个被遍历的,然后再继续去遍历其他子视图,我们来看一个demo:

在这里插入图片描述
可以看到touchView1先被添加到view中,随后再添加touchView2,我们来看一下subViews数组

在这里插入图片描述
可以看到touchView2在数组的尾部,这也就说明了倒序遍历就是从后面添加的视图向前遍历

二、手势识别

找到了合适的View,也就是第一响应者,如果是触摸事件,我们就要去识别是何种手势

使用不同的手势会调用不同次数的事件,这里我们不细讲,只要知道有这么一个过程即可

三、响应机制

在了解响应者链前,我们需要知道什么是响应者

UIResponder(响应者)

在 iOS 中,只有继承于 UIResponder 的对象、或者它本身才能成为响应者。很多常见的对象都可以相应事件,比如 UIApplication 、UIViewController、所有的 UIView(包括 UIWindow)
我们来看一张继承图
请添加图片描述
可以看到UIResponder提供了我们平时最常用的touchesBegan/touchesMoved/touchesEnded方法。此外还有如下几个属性比较重要:

  • isFirstResponder:判断该View是否为第一响应者。
  • canBecomeFirstResponder:判断该View是否可以成为第一响应者。
  • becomeFirstResponder:使该View成为第一响应者。
  • resignFirstResponder:取消View的第一响应者。

如果我们将一个view_A先加在view_B上,然后又加到view_C上,那么view_A.nextResponder指的是view_B

响应者链

找到第一响应者之后并且识别出手势后,我们就要确定由谁来响应这个事件了,如何理解这句话呢?
第一响应者不一定能响应事件,因为他可能并没有实现触摸事件

我们来以一个Demo来理解
在这里插入图片描述
在这里插入图片描述
红色的是V1,蓝色的是V2,V2是第一响应者

我们为我们的V1添加点击事件
在这里插入图片描述

我们点击蓝色区域
在这里插入图片描述
可以看到响应触摸事件的我们的V1,也就是红色区域,这也说明了第一响应者不一定能响应事件

这里需要注意的一点是如果我们要给视图添加触摸事件,一定要新建一个子类View,不能再UIViewC中重写touches实例方法,因为这样事件的响应者就是UIViewC而非你期望中的View,我们也以一个Demo来示范

在VC中重写方法
在这里插入图片描述

在VC中重写方法
在这里插入图片描述
可以看到当我点击空白区域时候响应的是VC,点击蓝色或是红色区域时响应的是V1,这是因为事件的传递是沿响应者链传递的,由此引出我们对响应者链的讨论

响应者链示意图:
在这里插入图片描述
在这里插入图片描述

  • Response Chain,响应链,一般我们称之为响应者链。
  • 在我们的 app 中,所有的视图都是按照一定的结构组织起来的,即树状层次结构,每个 view 都有自己的 superView,包括 controller 的 topmost view(即 controller 的 self.view)。
  • 当一个 view 被 add 到 superView 上的时候,它的 nextResponder 属性就会被指向它的 superView。
  • 当 controller 被初始化的时候,self.view(topmost view) 的 nextResponder 会被指向所在的 controller,而 controller 的 nextResponder 会被指向 self.view的superView。
  • 这样,整个 app 就通过 nextResponder 串成了一条链,这就是我们所说的响应者链。
  • 所以响应者链是一条虚拟的链,并没有一个对象来专门存储这样的一条链,而是通过 UIResponder 的属性串联起来的。
    @property(nonatomic, readonly, nullable) UIResponder *nextResponder;

总结一下响应者链的响应流程
判断当前视图能否响应,再去判断当前视图的nextResponder,如果是VCView,那么nextResponder就是VC
如果不是控制器的 View,上一个响应者就是SuperView

响应的大致的过程 第一响应者 –> super view –> ……–> view controller –> window –>Application

四、相关应用

扩大button点击范围

解决:给button加分类然后重写pointInside
实现步骤:

  • 自定义按钮:创建一个自定义按钮子类,继承自 UIButton。
  • 重写 point(inside:with:):在自定义按钮类中重写此方法。该方法接受一个点,并判断该点是否在视图的范围内。你可以扩展点击区域,以便更宽泛的区域内点击时视图仍然会接收点击事件。
  • 设定点击区域扩展的大小:可以设定需要扩大点击范围的值,在四个方向上(上、下、左、右)同时增大或仅针对特定方向。
// CustomButton.h
#import <UIKit/UIKit.h>@interface CustomButton : UIButton@property (nonatomic) UIEdgeInsets hitTestEdgeInsets;@end// CustomButton.m
#import "CustomButton.h"@implementation CustomButton- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {// 计算新的扩大后的点击区域CGRect largerFrame = CGRectMake(self.bounds.origin.x - self.hitTestEdgeInsets.left,self.bounds.origin.y - self.hitTestEdgeInsets.top,self.bounds.size.width + self.hitTestEdgeInsets.left + self.hitTestEdgeInsets.right,self.bounds.size.height + self.hitTestEdgeInsets.top + self.hitTestEdgeInsets.bottom);// 判断点是否在新的点击区域内return CGRectContainsPoint(largerFrame, point);
}@end

在你的视图控制器中,将自定义按钮的 hitTestEdgeInsets 属性设置为所需的值,以扩大点击区域:

// Example usage in a view controller
CustomButton *button = [[CustomButton alloc] initWithFrame:CGRectMake(100, 100, 100, 40)];
button.backgroundColor = [UIColor systemBlueColor];
[button setTitle:@"Click Me" forState:UIControlStateNormal];// 将点击区域向四个方向各扩展10个点
button.hitTestEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10);[self.view addSubview:button];

穿透事件

在这里插入图片描述
例如我们想点击蓝色区域时响应事件的是红色区域,但是第一响应者是蓝色区域,那么就需要我们重写(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event方法,让其无法成为响应者,这样就会让红色成为响应者

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {self.userInteractionEnabled = NO;return [super hitTest:point withEvent:event];}

总结

  • 当触摸事件发生后,系统会自动生成一个UIEvent对象,记录事件产生的时间和类型
  • 然后系统会将UIEvent事件加入到一个由UIApplication管理的事件队列中
  • 然后UIApplication将事件分发给UIWindow,主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件
  • 不断递归调用hitTest方法来找到第一响应者
  • 如果第一响应者无法响应事件,那么按照响应者链往上传递,也就是传递给自己的父视图
  • 一直传递直到UIApplication,如果都无法响应则事件被丢弃
    参考博客事件传递与响应 详解(精通iOS系列)

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

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

相关文章

苍穹外卖Day06笔记

疯玩了一个月&#xff0c;效率好低&#xff0c;今天开始捡起来苍穹外卖~ 1. 为什么不需要单独引入HttpClient的dependency&#xff1f; 因为我们在sky-common的pom.xml中已经引入了aliyun-sdk-oss的依赖&#xff0c;而这个依赖低层就引入了httpclinet的依赖&#xff0c;根据依…

Docker部署Metabase

文章目录 Docker安装MetabaseCentOS7安装Docker获取最新的 Docker 镜像启动Metabase容器在Metabase初始化时查看日志访问Metabase Metabase 的 ClickHouse 驱动程序安装环境简介删除容器创建容器下载click house驱动放入驱动重启容器将元数据库连接到 ClickHouse报错解决 Docke…

【华为OD机试C卷D卷】部门人力分配(C++/Java/Python)

【华为OD机试】-(A卷+B卷+C卷+D卷)-2024真题合集目录 【华为OD机试】-(C卷+D卷)-2024最新真题目录 题目描述 部门在进行需求开发时需要进行人力安排。 当前部门需要完成 N 个需求,需求用 requirements 表述,requirements[i] 表示第 i 个需求的工作量大小,单位:人月。 这部…

代码随想录算法训练营第36期DAY23

DAY23 530二叉搜索树的最小绝对差 /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(null…

YOLOv9改进策略 | 添加注意力篇 | 一文带你改进GAM、CBAM、CA、ECA等通道注意力机制和多头注意力机制

一、本文介绍 这篇文章给大家带来的改进机制是一个汇总篇&#xff0c;包含一些简单的注意力机制&#xff0c;本来一直不想发这些内容的&#xff08;网上教程太多了&#xff0c;发出来增加文章数量也没什么意义&#xff09;&#xff0c;但是群内的读者很多都问我这些机制所以单…

2. SVG的使用方式

可缩放矢量图形&#xff08;SVG&#xff09;是一种基于XML的图像格式&#xff0c;用于网络上的二维图形。SVG允许图形在不同尺寸下保持高质量&#xff0c;这使得它非常适合响应式设计。本文将介绍SVG的几种使用方式&#xff0c;包括实例代码、应用场景以及各自的优缺点。 1 内…

C++(函数高级)

函数默认参数 在C中&#xff0c;函数的形参列表中&#xff0c;形参是可以有默认值的 语法&#xff1a;返回值类型 函数名 &#xff08;参数 默认值&#xff09;{} #include<iostream> using namespace std;//函数默认参数 //如果我们传入自己的数据&#xff0c;就使用自…

PDPS15---安装过程---常遇问题---分享

目录 问题1 安装失败 1.1 运行第一步出错 1.2 解决 问题2 路径错误 2.1 错误 2.2 解决 问题3 运行失败 3.1 无法找到路径 3.2 原因分析 3.3 解决 问题4 拒绝访问 4.1 出现提示 4.2 分析 4.3 解决 问题5 许可证过期 5.1 PD找不到许可证 5.2 解决 问题1 安装失败…

Joplin:自由、安全、多功能的笔记应用

什么是 Joplin&#xff1f; Joplin是一款免费、开源的笔记和待办事项应用程序&#xff0c;可以处理整理到笔记本中的大量笔记。这些笔记是可搜索的&#xff0c;可以直接从应用程序或从您自己的文本编辑器中复制、标记和修改。笔记采用Markdown 格式 功能亮点 功能丰富&#x…

从“制造”到“智造”:“灯塔”经验助力中国制造业转型升级-转载

作者&#xff1a;Karel Eloot&#xff0c;侯文皓&#xff0c;Francisco Betti&#xff0c;Enno de Boer和Yves Giraud 作为中国实体经济的主体&#xff0c;制造业是推动中国经济发展乃至全球制造业持续增长的重要引擎。站在历史与未来交汇的新起点上&#xff0c;中国制造业将背…

Leetcode 3133. Minimum Array End

Leetcode 3133. Minimum Array End 1. 解题思路2. 代码实现 题目链接&#xff1a;3133. Minimum Array End 1. 解题思路 这一题由于要求所有的array当中所有的数字的与为目标值&#xff0c;因此目标值当中的1的位必须保证所有的数均为1&#xff0c;剩下的位置只需要保证有一…

如何在onshow中让子组件重新加载

如何在onshow中让子组件重新加载 今日bug解决记录 在开发uniapp过程中&#xff0c;当从当前页面返回上一级页面时&#xff0c;页面的子组件数据没有重新加载&#xff0c;导致没有展示最新数据。 知识点&#xff1a; uniapp组件生命周期 beforeCreate&#xff1a;在应用实例…

3D模型如何实现拖拽打开?---模大狮模型网

在当今数字化时代&#xff0c;3D技术的应用已经深入到各行各业&#xff0c;为用户带来了更加丰富、生动的体验。然而&#xff0c;对于一些用户来说&#xff0c;打开和查看3D模型可能会面临一些困难&#xff0c;特别是在无法拖拽打开时。本文将为您揭示解决这一问题的方法&#…

【C】语⾔内存函数--超详解

1. memcpy 使⽤和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。 这个函数在遇到 \0 的时候并不会停下来。 如果source和destination有任何的重叠&am…

数据结构与算法之树和二叉树的一些概念和性质

目录 前言 一、树的定义 二、树的若干术语 1.结点的度 2.叶子 3.双亲与孩子 4.兄弟 5.祖先 6.树的度 7.结点的层次 8.树的深度 9.有序树和无序树 10.森林 三、树的逻辑结构 四、树的存储结构 1.顺序存储 2.链式存储 五、二叉树 1.定义 2.二叉树的五种状态 …

SPA模式下的多页面跳转原理及实现

jQuery Mobile在SPA模式下的多页面跳转原理及实现案例 文章目录 jQuery Mobile在SPA模式下的多页面跳转原理及实现案例前言一、SPA的实现原理和代码分析1.实现原理说明&#xff08;1&#xff09;index.html&#xff08;2&#xff09;index.js&#xff08;3&#xff09;page2.ht…

前端css中线性渐变(linear-gradient)的使用

前端css中线性渐变 一、前言二、关键词句三、主要内容说明&#xff08;一&#xff09;、线性渐变方向1.角度调整方向2.负值角度&#xff0c;源码13.源码1运行效果4.关键字调整方向5.to right向右线性渐变&#xff0c;源码26.源码2运行效果 &#xff08;二&#xff09;、线性渐变…

今日总结2024/5/9

今日复习了朴素LCS,学习了LCS优化&#xff0c;以及LCIS 最长上升公共子序列 P1439 最长公共子序列 题目描述 给出 1,2,…,&#x1d45b; 的两个排列 &#x1d443;1​ 和 &#x1d443;2​ &#xff0c;求它们的最长公共子序列。 输入格式 第一行是一个数 &#x1d45b;。…

初识C语言——第十六天

C语言中的语句结构类型:顺序/选择/循环 分支语句 if else switch 循环语句 while for do whlie goto语句 代码练习:找两个整数的最大公约数和最小公倍数 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h>//int main() //{ // int age 60; // if (ag…

【ARM64 常见汇编指令学习 14.1 -- ARM 汇编 .align 和 .section】

文章目录 ARM 汇编 .align 和 .section.align.section示例 ARM 汇编 .align 和 .section 在ARM64&#xff08;或称为AArch64&#xff09;汇编语言中&#xff0c;.align 和 .section 是两个常用的指令&#xff0c;它们在代码中扮演着重要的角色&#xff0c;尤其是在控制内存对齐…