iOS UITableView自带滑动手势和父视图添加滑动手势冲突响应机制探索
场景
我们有时候会遇到这样的一个交互场景:我们有一个UITableView
放在一个弹窗中,这个弹窗可以通过滑动进行展示和消失(跟手滑动的方式),然后这个UITableView放在弹窗中,并且可以滚动,展示一些内容,比如商品信息,评论,(类似抖音的评论弹窗),并且下滑的时候,如果tableView已经滑动到了顶部,就可以响应滑动手势,继续向下滑动弹窗。
思路
首先,我们弹窗视图中有一个tableView,这个tableView是可以正常的滑动的,然后,我们在弹窗视图中添加一个滑动手势,手势的响应方法中,修改弹窗的frame。所以,这个弹窗视图是要响应手势的代理
方的,并且 在
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
代理方法中,如果gestureRecognizer 是自身的滑动手势,otherGestureRecognizer是tableView 的滑动手势,则需要支持同时响应的,即返回YES,同时,需要有个主意事项,就是如果我们的
tableView滚动到最顶部了,就需要设置tablView的滚动手势不支持响应,否则的话,就会导致 滚动到顶部的时候,tableView还会继续滚动,如果这个时候来回滑动tableView,就会造成弹窗和tableView 同时滚动的情况,这是我们不想要的,所以我们tablView滚动到顶部的时候,就需要设置tableView的pangesture.enabled = NO.
双滑动手势滚动响应机制
我们给弹窗添加一个滑动手势,响应方法为handlePan:
通过测试我们发现,我们手在tableView 上滚动的时候,每次执行
tableView 的 代理方法 scrollViewDidScroll 之前,都会执行 handlePan方法。
并且,在一次滑动(手没有脱离屏幕算同一次滑动)过程中,
如果响应方法 handlePan 中有设置过
self.tableView.panGestureRecognizer.enabled = NO; 就会导致
本次滑动中self.tableView 不会滚动,即便在self.tableView.panGestureRecognizer.enabled = NO后面设置了 self.tableView.panGestureRecognizer.enabled = YES也不会滚动
这说明,**在一次滑动手势的响应中, self.tableView.panGestureRecognizer.enabled = NO 的优先级是最高的
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{NSLog(@"哈哈哈哈哈这里是执行scrollViewDidScroll self.panNum是%ld", self.panNum);
}
- (void)handlePan:(UIPanGestureRecognizer *)pan
{self.tableView.panGestureRecognizer.enabled = YES;NSLog(@"哈哈哈哈哈这是第%ld次响应滑动手势handlePan 方法", self.panNum);if (self.panNum % 2 == 0) {self.tableView.panGestureRecognizer.enabled = NO;} else {self.tableView.panGestureRecognizer.enabled = YES;}self.tableView.panGestureRecognizer.enabled = YES;
}
以上测试的完整代码
//
// LBPangestureController.m
// TEXT
//
// Created by mac on 2024/7/7.
// Copyright © 2024 刘博. All rights reserved.
//#import "LBPangestureController.h"@interface LBPangestureController () <UITableViewDelegate, UITableViewDataSource, UIGestureRecognizerDelegate>@property (nonatomic, strong) UITableView *tableView;@property (nonatomic, strong) UIPanGestureRecognizer *pangesture;@property (nonatomic, assign) NSInteger panNum;@end@implementation LBPangestureController- (void)viewDidLoad {[super viewDidLoad];[self.view addSubview:self.tableView];[self.view addGestureRecognizer:self.pangesture];// Do any additional setup after loading the view.
}- (void)handlePan:(UIPanGestureRecognizer *)pan
{self.tableView.panGestureRecognizer.enabled = YES;NSLog(@"哈哈哈哈哈这是第%ld次响应滑动手势handlePan 方法", self.panNum);if (self.panNum % 2 == 0) {self.tableView.panGestureRecognizer.enabled = NO;} else {self.tableView.panGestureRecognizer.enabled = YES;}self.tableView.panGestureRecognizer.enabled = YES;
}#pragma mark - UITableViewDelegate, UITableViewDataSource- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([UITableViewCell class])];cell.textLabel.text = [NSString stringWithFormat:@"%ld", indexPath.row];return cell;
}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{return 100;
}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{return 60;
}#pragma mark - uiscrollViewdelegate- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{NSLog(@"哈哈哈哈哈这里是执行scrollViewDidScroll self.panNum是%ld", self.panNum);
}#pragma mark - gesturedelegate- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{if (gestureRecognizer == self.pangesture) {self.panNum ++;}return YES;
}- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{if (gestureRecognizer == self.pangesture && otherGestureRecognizer == self.tableView.panGestureRecognizer) {return YES;}return NO;
}#pragma mark - lazy load- (UITableView *)tableView
{if (!_tableView) {_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 100, 300, 400) style:UITableViewStylePlain];[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:NSStringFromClass([UITableViewCell class])];_tableView.delegate = self;_tableView.dataSource = self;_tableView.backgroundColor = [UIColor cyanColor];}return _tableView;
}- (UIPanGestureRecognizer *)pangesture
{if (!_pangesture) {_pangesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];_pangesture.delegate = self;}return _pangesture;
}/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end
相关文章:

iOS UITableView自带滑动手势和父视图添加滑动手势冲突响应机制探索
场景 我们有时候会遇到这样的一个交互场景:我们有一个UITableView 放在一个弹窗中,这个弹窗可以通过滑动进行展示和消失(跟手滑动的方式),然后这个UITableView放在弹窗中,并且可以滚动,展示一些…...

RAG实践:ES混合搜索BM25+kNN(cosine)
1 缘起 最近在研究与应用混合搜索, 存储介质为ES,ES作为大佬牌数据库, 非常友好地支持关键词检索和向量检索, 当然,支持混合检索(关键词检索向量检索), 是提升LLM响应质量RAG(Retri…...

论文去AIGC痕迹:避免AI写作被检测的技巧
在数字化时代,AI正以其卓越的能力重塑学术写作的面貌。AI论文工具的兴起,为研究者们提供了前所未有的便利,但同时也引发了关于学术诚信和原创性的热烈讨论。当AI辅助写作成为常态,如何确保论文的独创性和个人思想的体现࿰…...

C#使用异步方式调用同步方法的实现方法
使用异步方式调用同步方法,在此我们使用异步编程模型(APM)实现 1、定义异步委托和测试方法 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Task…...

【Go系列】 Go语言的入门
为什么要学习Go 从今天起,我们将一同启程探索 Go 语言的奥秘。我会用简单明了的方式,逐一讲解 Go 语言的各个知识点,帮助你从基础做起,一步步深化理解。不论你之前是否有过 Go 语言的接触经验,这个系列文章都将助你收获…...

Dify 与 Xinference 最佳组合 GPU 环境部署全流程
背景介绍 在前一篇文章 RAG 项目对比 之后,确定 Dify 目前最合适的 RAG 框架。本次就尝试在本地 GPU 设备上部署 Dify 服务。 Dify 是将模型的加载独立出去的,因此需要选择合适的模型加载框架。调研一番之后选择了 Xinference,理由如下&…...

MICCAI 2024Centerline Boundary Dice Loss for Vascular Segmentation
MICCAI 2024 Centerline Boundary Dice Loss for Vascular Segmentation MICCAI 2024Centerline Boundary Dice Loss for Vascular Segmentation中心线边界Dice损失用于血管分割**摘要**:1. 引言相关工作: 2. 方法预备知识Dice的变化 3 实验3.1 数据集3.2 设置3.3 结…...

golang验证Etherscan上的智能合约
文章目录 golang验证Etherscan上的智能合约为什么要验证智能合约如何使用golang去验证合约获取EtherscanAPI密钥Verify Source Code接口Check Source Code Verification Status接口演示示例及注意事项网络问题无法调用Etherscan接口(最重要的步骤) golan…...
Visual Studio编译优化选项
目录 /O1 和 /O2 /Ox 内联函数 虚函数优化 代码重排 循环优化 链接时间优化 代码分割 数学优化 其他优化选项 在Visual Studio中,编译优化选项是用于提高程序性能的重要工具。编译器提供了多种优化级别和选项,可以根据不同的需要进行选择。 在…...

sql业务场景分析思路参考
1、时间可以进行排序,也可以用聚合函数对时间求最大值max(时间) 例如下面的例子:取最晚入职的人,那就是将入职时间倒序排序,然后limit 1 表: 场景:查找最晚入职员工的所有信息 se…...
Django权限系统如何使用?
Django的权限系统是一个强大而灵活的特性,允许你控制不同用户对应用程序中资源的访问。以下是使用Django权限系统的几个基本步骤: 1. 定义模型权限 在你的models.py文件中,你可以为每个模型定义自定义权限。这通过在模型的Meta类里设置perm…...

基于整体学习的大幅面超高分遥感影像桥梁目标检测(含数据集下载地址)
文章摘要 在遥感图像(RSIs)中进行桥梁检测在各种应用中起着至关重要的作用,但与其他对象检测相比,桥梁检测面临独特的挑战。在RSIs中,桥梁在空间尺度和纵横比方面表现出相当大的变化。因此,为了确保桥梁的…...

逻辑回归模型(非回归问题,而是解决二分类问题)
目录: 一、Sigmoid激活函数:二、逻辑回归介绍:三、决策边界四、逻辑回归模型训练过程:1.训练目标:2.梯度下降调整参数: 一、Sigmoid激活函数: Sigmoid函数是构建逻辑回归模型的重要激活函数&am…...
QT的OpenGL渲染窗QOpenGLWidget Class
Qt - QOpenGLWidget (class) (runebook.dev) 一、说明 QOpenGLWidget 类是用于渲染 OpenGL 图形的小部件。从Qt 5.4就开始退出,它对于OpenGL有专门的配合设计。 二、QOpenGLWidget类的成员 2.1 Public类函数 QOpenGLWidget(QWidget *parent nullptr,Qt…...
单元测试和集成测试
软件测试中,单元测试和集成测试是比较常见的方法 单元测试:这是一种专注于最小可测试单元(通常是函数或方法)的测试,用于验证单个组件的行为是否符合预期。它通常由开发者自己完成,可以尽早发现问题&#…...
【JAVA入门】Day15 - 接口
【JAVA入门】Day15 - 接口 文章目录 【JAVA入门】Day15 - 接口一、接口是对“行为”的抽象二、接口的定义和使用三、接口中成员的特点四、接口和类之间的关系五、接口中新增的方法5.1 JDK8开始接口中新增的方法5.1.1 接口中的默认方法5.1.2 接口中的静态方法 5.2 JDK9 开始接口…...
ES6 之 Set 与 Map 数据结构要点总结(一)
Set 数据结构 Set 对象允许你存储任何类型的唯一值,无论是原始值还是对象引用。 特性: 所有值都是唯一的,没有重复。值的顺序是根据添加的顺序确定的。可以使用迭代器遍历 Set。 常用方法: 1. add(value):添加一个新…...

一文学会用RKE部署高可用Kubernetes集群
k8s架构图 RKE简介 RKE全称Rancher Kubernetes Engine,是一个快速的,多功能的 Kubernetes 安装工具。通过RKE,我们可以快速的安装一个高可用K8S集群。RKE 支持多种操作系统,包括 MacOS、Linux 和 Windows。 K8S原生安装需要的先…...

数据加密的常见方法
数据加密是一门历史悠久的技术,它通过加密算法和加密密钥将明文(原始的或未加密的数据)转变为密文,而解密则是通过解密算法和解密密钥将密文恢复为明文。这一技术的核心是密码学,它利用密码技术对信息进行加密,实现信息隐蔽&#…...
天童美语:推荐给孩子的人文历史纪录片
孩子们都有自己的偏好,有的孩子喜欢打游戏,有的孩子喜欢看剧看电影,有的孩子喜欢看书。针对不同的孩子我们要因材施教,所以,广州天童教育给大家推荐一下适合给孩子看的人文历史类的纪录片,让精美的画面&…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...

C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...