Xcode 16 调整 Provisioning Profiles 目录导致证书查不到

cronet demo 使用的 ninja 打包,查找 Provisioning Profiles 路径是 ~/Library/MobileDevice/Provisioning Profiles,但 Xcode 16 把该路径改为了 ~/Library/Developer/Xcode/UserData/Provisioning Profiles,导致在编译 cronetdemo 时找不到证书。

解决办法是把 Xcode 16 的路径下的证书拷贝一份到老的路径 ~/Library/MobileDevice/Provisioning Profiles 即可。

参考链接


Xcode16 调整 Provisioning Profiles 目录导致证书查不到

Mac应用第三方渠道发布指南

1.申请证书

Mac 应用有多种证书,主要包含以下几种:

Apple证书类型
Apple证书类型

  • Apple Development: Xcode 11之后Apple全平台开发证书
  • Apple Distribution: Xcode 11之后Apple全平台发布
  • Mac Development:用来开发和Debug的证书
  • Mac App Distribution:用来给APP文件签名后上传到Mac App Store
  • Mac Installer Distribution:用来给PKG文件签名后上传到Mac App Store
  • Developer ID Installer:用于给PKG文件签名,在非Mac App Store场景使用
  • Developer ID Application:用于给APP文件签名,在非Mac App Store场景使用

继续阅读Mac应用第三方渠道发布指南

Flutter编写HTTPS服务器

从磁盘加载证书:

从内存加载证书:

参考链接


Java环境下 SslSocket 服务端及客户端简单例子

客户端代码如下:

继续阅读Java环境下 SslSocket 服务端及客户端简单例子

网页检测 微信登录状态

现在很多网站、应用平台在登录的时候,都支持直接通过微信扫码登录。

最近我发现一个现象:以前需要扫二维码才能登录,而现在,如果你的电脑上已经运行了微信,它能直接检测到,然后点击一个按钮就可以实现登录了。

继续阅读网页检测 微信登录状态

Flutter 的生命周期

概述

生命周期是一个 widget 组件加载到卸载的整个周期,熟悉生命周期可以让我们在合适的时机做该做的事情。

Flutter 开发中,everything is widget,但我们一般都不用直接继承 Widget 类来实现一个新组件,我们通常会通过继承 StatelessWidgetStatefulWidget 来间接继承 Widget 类来实现。StatelessWidgetStatefulWidget 都是直接继承自 Widget 类,而这两个类也正是 Flutter 中非常重要的两个抽象类,它们引入了两种 Widget 模型。此文主要介绍这两种 widget 的生命周期。

StatelessWidget

StatelessWidget 是无状态的 Widget,一旦创建就不会发生变化,所以无法提供 setState 修改组件的状态,它内部属性应声明为 final,防止意外发生改变。所以 StatelessWidget 的生命周期只有一个,就是 buildbuild 是用来创建 Widget 的,但因为 build 在每次界面刷新的时候都会调用,所以不要在 build 里写业务逻辑,可以把业务逻辑写到你的 StatelessWidget 的构造函数里。其生命周期如下图:

继续阅读Flutter 的生命周期

Flutter手势冲突难题怎么破?几种解决方式大揭秘!

Flutter 应用开发中,手势处理是构建交互式界面的核心环节。然而当多个手势识别器或可滚动组件嵌套使用时,经常会出现手势冲突问题。

本文将深入探讨 Flutter 中解决手势冲突的各种方法,并分析其适用场景,帮助您掌握高效的手势管理策略。

1 手势冲突的根源

在理解如何解决手势冲突之前,我们需要先了解 Flutter 中手势系统的基本原理 :

Flutter 的手势识别基于 GestureRecognizer 竞争机制。当用户触发指针事件(PointerDown)时,多个手势识别器会进入 gesture arena 竞争,最终只有一个胜出。竞争的过程主要有两个阶段:

  • 命中测试阶段(Hit Test Phase):确定哪些 Widget 接收了手势事件。
  • 手势识别阶段(Gesture Recognition Phase):多个 Widget 可能会识别相同的手势,从而产生冲突。

开发过程中比较常见的手势冲突场景包括:

  • 嵌套滚动组件(如 PageView 中的 ListView
  • 多层手势检测器(如 InkWell 内部的 GestureDetector
  • 父子组件都监听相同类型手势事件
  • 多个手势识别器同时竞争同一区域

2 解决手势冲突的方式

针对不同的应用场景,Flutter 提供了不同的冲突的处理方式

2.1 HitTestBehavior (最轻量级)

通过控制 GestureDetectorbehavior 参数控制手势事件如何在Widget 树中传递。常见的 behavior 值有:

  • HitTestBehavior.translucent : 自身和子组件都能接收事件
  • HitTestBehavior.opaque: 拦截所有事件(即使透明区域)
  • HitTestBehavior.deferToChild: 默认值,优先传给子组件

有兴趣的话,可以尝试改变内外两个 GestureDetectorbehavior 的值来加深理解对这个处理方式的理解

适用场景

  • 父子组件都需要响应手势
  • 需要控制手势事件的传递层次(通过 behavior )
  • 简单按钮嵌套
2.2 AbsorbPointer/IgnorePointer组件

这两个组件在使用时,会完成拦截或忽略掉所有的手势:

  • IgnorePointer:使子 Widget 忽略所有手势事件,但仍会参与布局和绘制;
  • AbsorbPointer:拦截并消耗所有手势事件,子 Widget 无法接收手势,自身可以接收并处理事件。

适用场景

  • 临时禁用某个区域的手势
  • 阻止下层 Widget 接收手势事件;
  • 复杂UI中动态切换交互状态;

2.3 RawGestureDetector与手势竞技场

Flutter 的手势竞技场( GestureArena )机制允许自定义手势识别的竞争规则,通过使用底层的 RawGestureDetector 注册多个手势识别器,由手势竞技场决定胜出者,整个竞技的过程会经历

  1. 当指针按下时,所有识别器进入竞技场
  2. 通过 addPointer() 处理事件流
  3. 识别器声明是否"准备好"处理事件
  4. 竞技场选择获胜者(首个声明准备就绪的识别器)
  5. 胜出者接收后续事件,其他被拒绝

适用场景

  • 需要同时识别多种手势
  • 复杂手势组合(缩放+旋转+平移)
  • 自定义手势识别逻辑
2.4 Listener组件处理原始指针事件

直接通过 Listener 去处理最原始的指针事件,自由控制:

适用场景

  • 需要底层事件控制的场景
  • 高度定制化的交互需求
  • 性能关键型的手势处理
2.5 自定义 ScrollPhysics

通过继承 ScrollPhysics 类,可以自定义滚动行为,控制滚动事件的传递和处理。

适用场景

  • 嵌套滚动组件(如 PageViewListView 的冲突)
  • 需要精确控制滚动阈值和边界条件
2.6 使用 NotificationListener

通过监听滚动通知(如 ScrollNotification),可以在父组件中捕获并处理滚动事件,从而控制子组件的行为。

适用场景

  • 监听滚动状态并作出响应
  • 协调多层级滚动组件的行为

3 手势冲突的例子

项目的某一个场景中,会有一个 PageView 里面嵌套 ScrollView 的场景,而且这两个的滚动方向是一致的(都是竖向的滚动)。

这种情况下要怎样保证当 ScrollView 滑动到最底(最顶)时,能触发 PageView的 翻页呢?结合前面的介绍的处理手势冲突的几种方式,大家会选择哪个呢?

最开始笔者是选择了自定义 ScrollPhysics 的方式来尝试处理的,但发现最终也只能有一个组件能滚动(中间尝试不同解决方案的痛苦就一一细说了),这里最终是通过NotificationListener 来协调这两者的滚动的。(这个方案不一定是最好的)

4 总结

本文主要介绍了 Flutter 中手势冲突几种解决方案,从简单高效的 AbsorbPointer 到底层强大的 Listener,可以应对不同复杂度的交互场景。

可以根据不同的业务场景选择不同的解决方案,这里给几点在选择解决方案时可参考的点:

  • 准确识别冲突来源和类型
  • 评估交互的复杂程度
  • 考虑性能和维护成本

参考链接


Flutter手势冲突难题怎么破?几种解决方式大揭秘!

OpenBB的介绍以及如何使用OpenBB助力A股港股的金融数据分析

OpenBB 是一个开源的金融数据平台,旨在为投资者、分析师、研究人员和开发者提供免费、透明且易于使用的金融与宏观经济数据访问接口。它曾被认为是类似于彭博终端(Bloomberg Terminal)的功能性替代品,但完全开放源码,用户可以自由定制和扩展。

在一些文章中将 OpenBB 解释为 Open Bloomberg,这是个误解。尽管它常被视为“开源版彭博终端”,但其名称中的“BB”实际上源自黑莓公司的股票代码,而 OpenBB 的创始人此前曾在黑莓股票上亏损。

继续阅读OpenBB的介绍以及如何使用OpenBB助力A股港股的金融数据分析

Flutter手势冲突与手势竞争

手势冲突的原因

当多个手势同时出现在同一控件上时,就会发生手势冲突。这可能会导致系统无法准确识别用户的意图,从而导致错误的操作。iOS 上的 UIScrollView 是手势冲突的主要来源,因为它可以响应滚动、缩放和点击等各种手势。当 Flutter 视图与 UIScrollView 同时存在时,很容易发生手势冲突。

常见的冲突场景

最常见的场景是将 Flutter 视图嵌套在 UIScrollView 中。在这种情况下,UIScrollView 的滚动手势和 Flutter 视图的手势很容易发生冲突。例如,当用户在 Flutter 视图上拖动时,UIScrollView 可能将其误认为是滚动操作,从而导致 Flutter 视图无法响应拖动手势。

解决方案:手势竞技场

解决手势冲突的最有效方法之一是使用 Flutter 的手势竞技场。这是一个负责协调手势的系统,可确保同一时间只有一个手势被识别。要使用手势竞技场,需要在 Flutter 视图的最顶层添加一个 GestureRecognizer Widget,并将其作为竞技场的子控件。

手势竞技场的使用

以下是使用手势竞技场的示例代码:

通过使用这种方法,Flutter 视图的手势和 UIScrollView 的手势可以同时响应,互不干扰,从而完美解决 iOS 上的 Flutter 页面手势冲突问题。

常见问题解答

1. 为什么手势冲突在 iOS 上很常见?

因为 iOS 上的 UIScrollView 可以响应多种手势,并且它经常与 Flutter 视图一起使用,这可能导致手势冲突。

2. 手势竞技场是如何工作的?

手势竞技场是一个负责协调手势的系统,可确保同一时间只有一个手势被识别。它通过让手势识别器注册自己并协调它们的活动来实现此目的。

3. 如何在 Flutter 中使用手势竞技场?

在 Flutter 视图的最顶层添加一个 GestureRecognizer Widget,并将其作为竞技场的子控件。

4. 除了手势竞技场,还有其他解决手势冲突的方法吗?

是的,还有其他方法,例如使用 GestureDetector Widget 或重写控件的手势识别逻辑。

5. 为什么解决手势冲突很重要?

解决手势冲突很重要,因为它可以防止错误的操作,并确保用户获得流畅、无缝的体验。

参考链接