简体中文 | English
基于 CaiWanFeng/PiP 修改的个人学习与测试版本。
全局高刷通过系统画中画悬浮窗辅助部分 iOS App 恢复更高的自适应刷新率表现1-120Hz。将悬浮窗拖动并吸附到屏幕侧边后,可用于改善部分被限制在 1-80Hz 的场景体验。
它主要面向 ProMotion 设备在部分 App 或系统场景中被限制到 80Hz 左右的情况,通过画中画悬浮窗持续请求高刷新率,帮助这些场景恢复更接近 120Hz 的滑动和动画表现。具体效果仍取决于设备型号、系统版本、前台 App 自身策略以及悬浮窗是否正常吸附和存活。
本项目是在原版 PiP 示例基础上继续开发的修改版,原作者为 CaiWanFeng。当前版本由 Yoroin 完善,主要增加了后台保活、悬浮窗高度调节(可完全隐藏悬浮窗)、iOS 26 液态玻璃 UI 适配、低版本 iOS 兼容处理和调试日志功能。
请注意:
- 本项目仅用于学习、研究和个人设备测试。
- 效果依赖系统画中画、设备刷新率能力和具体 App 的刷新率策略。
- 60Hz 设备或本身锁定 60Hz 的 App 无法通过本项目变成 120Hz。
- 后台保活并非系统级永久后台权限,仍可能受到内存压力、系统策略或其他画中画 App 的影响。
底层方案说明:
| 方案 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|
| 默认方案:VideoCall | 支持最低 0.1pt,可做到视觉上完全隐藏;兼容性更好,日常使用更稳定 | 会强拉全局 120Hz,部分自身锁 60Hz 的游戏或弹幕场景可能出现不同步卡顿 | 大多数 App、锁 80Hz 场景、需要完全隐藏悬浮窗的用户 |
| 新方案:PlayerLayer | 可改善部分锁 60Hz App 与 120Hz 不同步导致的卡顿,例如 B 站弹幕一快一慢、荒野乱斗大厅偶尔掉帧 | 受底层限制最低 1pt,无法完全隐藏,视觉上可能留下一条细线;属于测试入口 | 仅建议遇到锁 60Hz 场景卡顿时尝试 |
简单来说:默认方案隐藏能力更好,适合大多数用户;新方案主要用于解决特定锁 60Hz 场景的卡顿问题,但无法做到 0.1pt 完全隐藏。
- 悬浮窗后台保活
- 自定义悬浮窗高度,最低支持 0.1pt
- 支持调节侧边吸附框大小
- 支持开启/停止悬浮窗内容滚动
- 支持记忆悬浮窗高度
- 帧率演示页面,用于对比 80Hz 和 120Hz 滑动体验
- 使用教程与常见问题页面
- iOS 26 液态玻璃风格适配
- 旧版 iOS 使用高斯模糊风格适配
- iOS 15 / iOS 16 低版本兼容优化
- 调试模式,可复制最近运行日志用于反馈问题
- 打开 App,点击首页的“开启悬浮窗”按钮。
- 将悬浮窗拖动到屏幕侧边并吸附。
- 如需隐藏悬浮窗,可在开启后将悬浮窗高度调节至 0.1pt。
- 如遇问题,可在“关于”页点击“常见问题”右侧的工具按钮,打开调试模式后复制调试日志。
如果你只是想借用默认 VideoCall 方案实现一个可自定义高度的画中画悬浮窗,而不需要本项目的“强拉 120Hz”能力,可以保留 AVPictureInPictureVideoCallViewController + AVPictureInPictureController.ContentSource 这条路线。
核心思路是创建一个透明的 AVPictureInPictureVideoCallViewController,通过 preferredContentSize 控制悬浮窗尺寸,再把自己的自定义 View 挂到这个 content view 里:
let contentController = AVPictureInPictureVideoCallViewController()
contentController.preferredContentSize = CGSize(width: 300, height: customHeight)
contentController.view.backgroundColor = .clear
contentController.view.isOpaque = false
let contentSource = AVPictureInPictureController.ContentSource(
activeVideoCallSourceView: sourceView,
contentViewController: contentController
)
let pipController = AVPictureInPictureController(contentSource: contentSource)后续调节高度时,同步更新 preferredContentSize 和你自己的内容 View 约束即可。需要视觉隐藏时,可以把高度调到很小,例如 0.1pt;如果不需要完全隐藏,也可以使用更保守的高度。
如果不需要强拉 120Hz,建议不要复制本项目的高刷驱动字段:
- 不需要在
Info.plist中启用CADisableMinimumFrameDurationOnPhone - 不要把
CADisplayLink.preferredFrameRateRange固定为minimum = maximum = preferred = 120 - 不要把
preferredFramesPerSecond固定为120 - 如需保留 DisplayLink,用系统自适应即可,例如:
if #available(iOS 15.0, *) {
displayLink.preferredFrameRateRange = CAFrameRateRange(
minimum: 30,
maximum: Float(UIScreen.main.maximumFramesPerSecond),
preferred: 0
)
} else {
displayLink.preferredFramesPerSecond = 0
}简单来说:只做自定义高度时,保留 VideoCall 的 PiP 容器和 preferredContentSize;关闭强制 120Hz 相关字段,让系统自己决定刷新率。
项目导出的通用未签名 IPA 可通过以下工具自行签名安装:
- 牛蛙助手
- AltStore
- Sideloadly
- TrollStore 等其他支持自签的工具
请使用自己的 Apple ID、证书或设备环境完成签名安装。
- 注:此次更新重点解决问题,高刷作用字段回滚至1.0.7稳定版,解决部分iOS版本解锁120失效的问题;新增底层方案切换,解决b站弹幕和荒野乱斗卡顿,缺点无法完全隐藏最低1pt,原因,默认可隐藏悬浮窗底层会强拉120导致锁60的app卡顿,锁80的app不受影响
- 新增首页按钮 一键0.1pt 用于悬浮窗吸附后快速调节高度
- 优化悬浮窗的组件,避免0.1pt时屏幕出现两个白点(仅对iOS16+生效)
- 优化悬浮窗隐藏后的资源占用:当高度调至 0.1pt 时,暂停文字滚动和时钟刷新,减少长期后台挂载时的无效开销和发热
- 去除 后台中断通知beta 减少误报情况
- 优化深色模式切换逻辑,按钮移至首页
- 快捷指令尝试适配低版本iOS,如无法使用,请在更多设置-手动导入快捷指令使用
- 新增“底层切换”测试入口(日常用户请忽略):更多设置-底层切换-新方案。新方案仅用于解决因部分游戏和弹幕自身锁60而与120帧率不同步导致的卡顿,表现为b站弹幕一快一慢以及荒野乱斗大厅偶尔掉帧,新方案PlayerLayer参考悬浮时钟受底层限制最低1pt,无法完全隐藏,视觉上会有一条细线,默认方案VideoCall仍保留0.1pt隐藏能力,非必要请默认使用老方案
- 增加英文适配
- 简化调试模式,优化逻辑,不打开调试模式时完全停止日志记录减少性能开销
- 优化帧率检测逻辑
- 优化部分动画细节
- 默认启用原有文本悬浮窗、默认启用悬浮窗被挤通知(需要同意授权)、默认启用悬浮窗状态常驻、默认启用记忆悬浮窗高度
- 新增 手动填写高度
- 已知问题:直接用快捷指令一键开启悬浮窗隐藏会导致悬浮窗没有吸附到侧面,阻止熄屏,一般还是建议先启用悬浮窗,拖到侧面吸附后再点击一键0.1pt按钮
- 使用 Xcode 27 beta 构建,适配 iOS 15-iOS 27
- 新增悬浮窗时间、网速、帧率检测(因打开悬浮窗后全局默认120hz,帧率检测功能需要先临时关闭帧率演示的强制120hz开关)
- iOS 26 以下强制禁用时间悬浮窗,避免旧系统启用后导致全局120Hz失效;普通文本悬浮窗不受影响
- 首页更多设置新增 深色模式 开关,默认关闭时跟随系统设置,开启后固定使用深色模式
- 首页更多设置新增 悬浮窗被挤通知 和 后台中断通知 beta 两个独立开关;被挤通知用于其他画中画挤掉悬浮窗时实时提醒(一般只开这个就够用了)。后台中断通知 beta 默认关闭,通过定时轮询和预排本地通知辅助判断后台是否仍存活;频率主要影响异常发现速度和误报风险,不代表耗电量线性增加
- 优化首页布局稳定性,修复部分状态切换后页面轻微错位
- 新增系统快捷指令:打开并隐藏悬浮窗、打开悬浮窗、隐藏悬浮窗,便于放在控制中心一键操作;添加入口为长按控制中心-新增快捷指令-选中全局高刷,控制中心添加快捷指令仅支持 iOS 18+(如果屏幕上出现两个点是因为悬浮窗的关闭按钮没有隐藏,让悬浮窗恢复正常大小后点一下即可,下次会自动隐藏)
- 新增悬浮窗状态常驻开关,便于查看存活时间
- 适配深色模式桌面图标
- 优化悬浮窗停止流程
- 优化强制帧率演示页面描述,此开关目前开启和关闭都将影响悬浮窗的120hz功能
- 为了减少耗电量,经过实测对比后APP将默认启用为更为省电的仅PiP保活新方案,后台保活效果仍为显著,且解决了小部分场景下的音频冲突问题
- 可通过版本号-下方或首页查看当前保活模式
- 不再推荐使用老方案,如有需求可再自行前往调试模式-自由切换
- 首页新增悬浮窗状态检测,方便查看是否生效以及隐藏和是否被杀后台,点击可查看每次打开后的持续运行时间以及上次关闭时间,便于判断后台留存时间
- 首页停止滚动按钮移至二级菜单,防止误解
- 调试模式新增 保活方案切换 开关,可尝试切换为更省电的仅PiP保活方案,但后台留存率可能下降可能出现低版本兼容性问题,可自行选择
- 修复关闭悬浮窗后进入后台可能自动重新开启的问题
- 调试模式新增复制诊断日志功能,用于辅助排查耗电变化和推断后台保活中断时间段
- 修复iOS16部分用户卡顿的问题,修复iOS16部分用户相机可能导致的闪退问题以及自定义悬浮窗高度不生效的问题(感谢两位老铁的崩溃日志和测试)
- 修复部分用户反馈的音频冲突问题
- 优化旧版iOS系统的UI,未适配液态玻璃的组件采用高斯模糊
- 修复低版本iOS设备闪退问题,已在iOS15.8设备调试通过
- 对“滚动悬浮窗”增加默认记忆功能;首页新增 记忆悬浮窗高度 开关
- 尝试修复iOS16低版本无法打开悬浮窗的问题
- 调整自定义悬浮窗的最低值为0.1pt,可以做到完全隐藏悬浮窗
- 去除旋转窗口功能
- 增加自定义悬浮窗高度功能,可通过滑块无级调节
- 增加关闭/开启滚动功能
- 在原版基础上增加后台保活功能和修改悬浮窗大小
关于页提供“调试模式”开关。开启后可以复制最近运行日志,方便定位:
- 悬浮窗是否成功准备
- 系统是否允许开启画中画
- 前后台保活状态
- 音频中断与恢复
- 低版本 iOS 兼容分支状态
日志仅保存在本机,不会联网上传。用户主动点击复制后,才会写入剪贴板。
本项目基于 CaiWanFeng/PiP 修改开发,感谢原作者 CaiWanFeng 提供原始 PiP 示例。
- 原项目:CaiWanFeng/PiP
- 原作者:CaiWanFeng
- 当前项目:Yoroin/GlobalRefresh-PiP
- 当前修改版维护:Yoroin
如果基于本项目继续修改、分发或发布 App,请保留原作者 CaiWanFeng、当前修改版 Yoroin 以及对应项目地址。请勿将本项目或其修改版声称为完全原创作品。
本项目仅供学习和个人测试使用。使用者需要自行承担安装、签名、使用过程中的风险。请勿将本项目用于违反平台规则、商业侵权或其他不当用途。
