引导页是App中的基本功能,指导用户理解某些操作或版本变化等等。
引导页可能出现在任何时候,页面内容会根据可交互度增加而增加,而且,引导页一般为一次性展示,页面存在过多的引导页逻辑,会影响到项目功能的架构设计。
这里分享一种基于swift dynomic replacement的解决方案:
一、方法替换:
extension HomeContainerViewController {
@_dynamicReplacement(for: viewWillAppear(_:))
func guidance_viewWillAppear(_ animated: Bool) {
viewWillAppear(animated)
if AppStatus.guideForHome.isValid { return }
// display
}
}
在本案例中,引导页触发点是viewWillAppear,通过替换方法截取触发时机,通过判断条件,展示引导页。
@_dynamicReplacement是swift 5.0之后提供的方法,使用条件:a、自定义类;b、带有dynamic标识符。不支持对原生类方法的替换,比如UIView、UIViewController等;
触发时机一般是某个类的某个方法,比如按钮点击、手势触发、App或实例生命周期方法等;
状态存储,建议针对引导项作单独存储,便于版本升级管理(清理),可以使用UserDefault-suitname方式,创建本地存储,状态值采用懒加载:
lazy var isValid = UserDefaults(suiteName: "guide")?.bool(forKey: "guideForHome") ?? false
二、引导页展示
present(GuideForHomeViewController(self), animated: true, completion: nil)
modalPresentationStyle = .overFullScreen
modalTransitionStyle = .crossDissolve
view.backgroundColor = .clear
采用present方式,配合转场特性,可以非常平滑的展示出引导页。设置背景色透明或半透明,可以更方便引导页与业务页面结合。
三、内容绘制
let timeFrame = timeView.superview?.convert(timeView.frame, to: view)
guideImageView.frame = timeFrame
guideImageView.image = UIGraphicsImageRenderer(size: timeFrame.size)
.image(actions: { (renderer) in timeView.layer.render(in: renderer.cgContext) })
UIGraphicsImageRenderer是目前iOS图片处理的几个API中最快的一个。将原始view提取成image到 guideImageView中,实现高亮效果。如果需要流程事件响应,可以分多个step,分别展示不同步骤的引导。
四、事件更新
AppStatus.guideForHome.save(true)
dismiss(animated: true, completion: nil)
在引导结束后,更新状态,退出引导页。
最终效果图:

网友评论