001project_wildgrowth/ios/WildGrowth/COMPLETION_强力侧滑版_审查报告.md

4.9 KiB
Raw Blame History

完成页「强力侧滑版」— 审查报告(禁止应用)

审查对象:粉紫勋章视觉 + RobustSwipeBackEnablerdidMove + viewDidAppear 双节点强制开启侧滑)
结论:仅审查,不修改仓库内任何文件。


一、问题与方案对应

问题 方案 审查结论
隐藏导航栏后侧滑返回失效 UIViewController 子类在 didMove(toParent:)viewDidAppear 两处调用 enableGesture() 思路正确,双节点可提高找回手势的概率
之前 SwipeBackEnabler 时机不对或被覆盖 使用自定义 SwipeBackController 继承 UIViewController,在生命周期中多次执行 比仅用 updateUIViewController 的 Representable 更稳

二、强力侧滑实现审查

2.1 RobustSwipeBackEnabler + SwipeBackController

  • RepresentablemakeUIViewController 返回 SwipeBackController()updateUIViewController 为空,符合「只挂一个控制器做生命周期」的用法。
  • SwipeBackController
    • didMove(toParent:):视图被加入/移出父控制器时调用,此时通常已进入导航栈,可拿到 navigationController
    • viewDidAppear:每次该页显示时再执行一次,可应对 SwiftUI 更新或系统把手势关掉的情况。
  • enableGesture()
    nc.interactivePopGestureRecognizer?.delegate = nil + isEnabled = true 是常见做法,用于在隐藏导航栏时恢复全屏侧滑。逻辑正确。

2.2 潜在注意点(非否决项)

  1. 视图层级.background(RobustSwipeBackEnabler()) 会把 SwipeBackController 的 view 作为 CompletionView 的底层。SwiftUI 的 NavigationStack 对应底层会有一个 UINavigationControllerself.navigationController 应是该栈,因此一般能正确找到。若将来把 CompletionView 放在非 NavigationStack 的容器里,需再确认 navigationController 是否仍为预期栈。
  2. 多次执行didMove / viewDidAppear 可能被多次调用(例如 SwiftUI 重绘、present 方式变化),重复执行 enableGesture() 无副作用,可接受。
  3. 真机验证:建议在真机上从「发现 / 技能 / 我的」三个 Tab 分别进入完成页,各做几次右滑返回,确认无偶发失效;若仍有失效,可再在 viewWillAppear 或短延迟 DispatchQueue.main.async 中补一次 enableGesture()

三、视觉与交互审查

3.1 与需求对照

需求 实现 结论
粉紫勋章:点前灰色+「完成」,点后粉紫+「共完成 XX 节」 未激活:灰底 + 灰边 + 「完成」;激活:粉紫渐变圆 + 白字「共完成 / N 小节」+ 冲击波 一致
顶部无返回按钮,只有标题「已完成」 ZStack 中仅 Text("已完成"),无 Button 一致
底部淡蓝按钮、无箭头 Text("回到我的内容").foregroundColor(.brandVital)Capsule().fill(Color.brandVital.opacity(0.08)),无 SF Symbol 一致
右滑回最后一节 依赖 RobustSwipeBackEnabler 见上
底部按钮回技能页根 handleReturnToRoot()navStore.switchToGrowthTab() 一致

3.2 配色与 DesignSystem

  • 方案中本地定义:
    • cyberPink = Color(red: 1.0, green: 0.25, blue: 0.50) → 等价 #FF4081
    • cyberPurple = Color(red: 0.54, green: 0.31, blue: 1.0) → 等价 #8A4FFF
  • DesignSystem 中已有:
    • Color.cyberNeon = #FF4081
    • Color.cyberIris = #8A4FFF
  • 建议(可选):将勋章渐变的 cyberPink / cyberPurple 改为 Color.cyberNeon / Color.cyberIris,避免重复定义并统一设计系统;若你希望完成页与 DesignSystem 解耦则可保留当前写法。

3.3 其他细节

  • 冲击波:rippleScale 从 1.0 到 1.8、rippleOpacity 从 1.0 到 0时长 0.8s,视觉合理。
  • 震动:UIImpactFeedbackGenerator(style: .heavy),与「点亮」动作匹配。
  • 底部按钮常驻显示(不依赖 isActive),与「回到我的内容」随时可点一致。

四、接口与调用方

  • CompletionView 仍为三参:courseId, courseTitle, completedLessonCount,依赖 @EnvironmentObject navStore
  • GrowthView / ProfileView / DiscoveryView 无需改构造或传参。

五、审查结论汇总

结论
强力侧滑方案 双生命周期节点didMove + viewDidAppear合理实现正确建议真机多入口验证必要时可再加 viewWillAppear 或短延迟兜底。
粉紫勋章视觉 与描述一致;可选改用 DesignSystem 的 cyberNeon/cyberIris 统一色值。
顶部 / 底部 / 交互 符合「无返回、仅标题、淡蓝按钮无箭头、底部回技能页根」的要求。
全量替换范围 仅替换 CompletionView.swift 即可VerticalScreenPlayerView 等不动。

未对仓库内任何文件进行修改。