前言
距离VTMagic正式开源已经过去整整一个月,这短短的时间里收获了九百多颗star,在GitHub月榜Objective-C语言中,其排名基本一直维持在前三。目前第一是雅虎的AppDevKit,第三名是大家熟知的AFNetworking。坦白说,这样的成绩完全出乎我的预料,大家对VTMagic的认可让我满怀欣喜的同时也变得有些忐忑不安。针对VTMagic的改进,我慢慢开始变得谨慎,每一次改动都需要不断测试验证,以保证其可以正常运行。个人的力量是微小的,希望能与各位江湖高手一起完善VTMagic,参与开源项目将会是一件很有趣的事!
正文
在上一篇文章中,已经初步介绍了VTMagic的部分特性和基本使用,同时也收到了不少反馈,本文将进一步介绍VTMagic使用中的一些要点和技巧,并针对部分反馈做一些总结,希望对各位开发者能有所帮助。
重用机制
该机制是整个框架的核心,它保证了单个模块中即使有数十上百个页面,应用内存依旧可控,不会出现突然暴涨,甚至被系统强制杀死的情况。在预加载机制下,VTMagic默认会加载当前页面和下一个页面,也就是说同时被加载的页面可能有两个,也可能有三个,具体视当前页面的位置而定。若当前页面处于两侧边缘,则被加载的页面有两个,若在中间则会有三个页面被加载。这也是有些开发者反馈的viewControllerAtPage:
方法会被多次调用的原因。
而之前加载的其它页面则会在不需要时被移除,并放到内部缓存池中等待重用。当某个页面即将被重用时,方法vtm_prepareForReuse
会被调用,该方法属于协议VTMagicReuseProtocol
,需要开发者在各子页面中手动重写,通常可以在这个方法中清除页面旧数据、修正页面偏移等。
需要说明的是,可以通过将属性needPreloading
置为NO
来关闭预加载机制。在预加载机制关闭的情况下,VTMagic只会加载当前显示的页面,而不再预加载下一页,同时点击菜单项切换时,页面也不再有切换动画。
生命周期方法
当某个子页面出现或消失时,VTMagic能准确触发其相应的生命周期方法(viewWillAppear:
等)。如果该页面是可重用的,则可以将网络请求放在viewDidAppear:
方法中,然后根据menuInfo.menuId
去请求当前菜单项的对应数据,作为必要的补充,请求时应该判断一下页面是否已经有了最新数据;与之相对的,我们应该在viewWillDisappear:
或viewDidDisappear:
方法中将网络请求取消掉,以免被重用后页面数据错乱和造成不必要的流量开销。而如果页面是唯一的,即不会有其它页面重用该页面,这种情况下也可以将网络请求放在viewDidLoad
方法中,特别是当预加载逻辑关闭时,即needPreloading
为NO
时。
谈到网络请求就不得不说加载本地数据的问题。针对可重用页面,当其menuInfo
改变时(可重写menuInfo
的setter
方法),我们通常需要为页面加载缓存数据,以保证滑动切换时能有良好的用户体验。关于缓存数据,可以是从数据库中读取,也可以直接将之前的页面数据保存到某个变量中以供后来使用,甚至可以从plist文件中获得,根据具体情况可灵活选择。
刷新和切换
-
reloadData
方法会重新加载所有页面; -
reloadDataToPage:
方法会在重新加载所有页面时,同步聚焦到指定页面; -
switchToPage:animated:
方法用于在需要的时候切换到指定页面。
以上三个方法的使用场景各有不同,可根据具体情况灵活使用。需要注意的是,应尽可能避免在viewWillAppear:
和 viewWillDisappear:
方法中调用以上方法,否则会造成某些页面的生命周期方法不能准确触发,控制台会输出类似Unbalanced calls to begin/end appearance transitions for <VTGridViewController: 0x7fc3e2d43a70>
的警告。这是因为这时的currentViewController
与之后viewDidAppear:
、viewDidDisappear:
方法中的currentViewController
不是同一个,也就是说currentViewController
的生命周期没有完整触发。而在viewDidLoad
、viewDidAppear:
、viewDidDisappear:
或者其它地方调用以上方法都是没问题的。
多层嵌套
VTMagic支持多层嵌套,也就是在子页面中可以再嵌套一个VTMagic,类似需求一般常见于iPad项目,其使用原则与单个VTMagic的使用一致,并无其它明显区别。
跨层级业务处理
为方便跨层级处理业务,VTMagic提供了在子页面中直接访问上层最近主控制器的方法self.magicController
,甚至你可以进一步通过self.magicController. magicView
拿到当前的magicView
。当然,你也可以通过self.vtm_pageIndex
获取当前页面的索引。同样的,在主控制器中可以通过self.currentViewController
和self.currentPage
获取当前显示的页面和索引。
自定义组件
VTMagic中几乎所有组件都支持自定义,框架本身主要提供核心的切换逻辑处理和良好的性能管理,开发者可根据业务需要自定义对外接口提供的任意组件。
自定义menuItem
你可以在menuItemAtIndex:
方法中返回自定义的任意menuItem
,只要它是UIBUtton
类型即可。menuItem
是顶部菜单栏中的单个菜单项,其可以支持文本、图片、文本+图片等几种格式。可见菜单栏文本的颜色和字体就是通过修改menuItem
的文本和颜色来实现的,VTMagic本身并不直接提供修改文本和字体的接口。
自定义菜单栏两侧视图
可以通过属性leftNavigatoinItem
和rightNavigatoinItem
在顶部菜单栏两侧添加任意视图,需要注意的是,被添加的视图应该有确定的size,然后VTMagic会自动完成相应布局。
自定义sliderView
由于需求各有不同,VTMagic提供的下划线、气泡等样式可能都不是你想要的,这种情况下你可以通过setSliderView:
方法来自定义任意样式的sliderView
,比如类似demo中的显示一个三角标识等。
自定义separatorView
如果需要,你甚至可以通过方法setSeparatorView:
自定义顶部导航分割线,不过一般情况下应该是没这必要的。
其它
-
VTMagic中有许多有意思的小feature,比如
scrollEnabled
、switchEnabled
、switchEvent
以及navigationInset
等等,详情请参见VTMagicView.h
文件。 - 关于VTMagic的所有重要修改都会记录在GitHub上的变更日志中,想知道每个版本都有哪些更新,可查阅该文件。
结束语
最后,按照惯例,如果你喜欢这个轮子,请留下一颗star,这是对作者最大的鼓励和支持,拜谢!!!假如你有更好的想法或方案,也欢迎提交pull request!!!GitHub地址