作者 |刘欣
责编|郭芮
每年iOS SDK的升级对于从事iOS开发的同学来说,犹如噩梦一般,因为每次升级都会带来大大小小的坑。相信每个iOS开发者都体会过其中的辛酸。今天和大家分享一下我的一个与此相关的填坑经历。记得那年,iPhone4和iPad2横空出世,是市面上的主流机型,iOS SDK版本还是4.3。
功能需求
当时做的一个功能要求简化后大概是这样的:当前UIViewController是固定的,也就是不会pop当前的UIViewController,也不会push或者present新的UIViewController。当前UIViewController对应的UIView是分页的,左右滑动可以切换页面。这个功能要求是,左右滑动切换页面时,需要根据目标页面的方向设置,有时候需要强制旋转目标页面。比如,当前iPad的方向是横向(landscape),我向右滑动切换到第二页时,第二页只支持纵向(portrait)方向,此时需要将这一页强制转换为纵向方向。
最早的实现
众所周知,苹果一个比较坑的地方就是开放的SDK是比较有限的,特别是当时的iOS SDK 4.3。很多功能通过开放的API很不好实现,上述的功能就是一个例子。当然,这难不倒我策天才般的iOS开发同学。一会就试出来实际上UIViewController上有一个私有方法(private method)就叫[UIViewController rotate],提供的功能刚好就是我们需要的。但遗憾的是由于苹果审核机制,它是不允许上架app中使用iOS SDK的私有方法的。(至今我还是不明白为什么这个方法不给开放出来给大家用。)经过进一步的研究,我们尝试出来的一个解决方法是这样的:
就是在当前的UIViewController上present一个新的UIViewController,然后马上再dismiss掉。看起来好像啥事都没做。实际上这几行代码的唯一作用是让系统(UIKit)重新评估(re-evaluate)当前UIViewController应该处于的方向,也就是说旋转相关的系统回调函数[UIViewController shouldAutorotate]和[UIViewController supportedInterfaceOrientations]会被再次调用。此时我们可以趁机在这两个回调函数中返回合适的值,使得当前的UIViewController的方向强制变成我们所希望的。
赞,一个略显tricky但是完美的解决方案!产品经理看了很满意,皆大欢喜。
第一个坑来了
这个功能一直很好用,bug也基本没有。一切都这么完美,直到一年多后,某测试同学手里捧着升级到iOS 5.0的iPad急吼吼跑到我们的开发同学面前,“粗大事了!这功能完全挂了!”(BTW,该测试同学目前已然是我司资深测试架构师)。稍微调试一下就发现原因是在iOS SDK 5.0中,上面的这几行代码调用完以后,这次系统(UIKit)并不会重新评估当前UIViewController应该处于的方向,也意味着我们并没有机会来改变当前UIViewController的方向了。苍天啊,大地啊!苹果你咋这么坑呢?行为改了也不说一声?其实前面那个方法苹果也没有在开发文档里提过,完全是靠大家自己试出来的,所以这个方法不管用了,也的确没地说理去。
如果找不到新的解决方法,可是会产生严重的regression的!经过开发同学的不懈努力,愣是又找到一个方法:
其原理和上面那个方法类似。反正就是要迫使系统(UIKit)重新评估当前UIViewController应该处于的方向。
赞,新的解决方案!Make MSTR mobile app great again!
第二个坑来了
又过了一年多,iOS6发布,还是上面那位测试同学拿着升级后的iPad又过来了,脸上写着“我就知道会这样”。说到:“额…你们快来看看!这个功能好像又挂了!”。当时我们的第一反应是iOS5的那个方法又不管用了,调试后确认果然是的。然后仔细看了iOS SDK 6的文档,这次方向和旋转又换了新玩法:
意思我们这次需要当前的UIViewController和它所在的UINavagationController一起改。于是新的解决方案是这样的,对于UIViewController,代码又变回和iOS4一样了:
对于UINavagationController,我们需要继承或者使用method swizzling来改变[UIViewController shouldAutorotate]和[UIViewController supportedInterfaceOrientations]这两个回调函数的实现:
终于,在接下来的几年中,iOS SDK的升级都没有影响这个功能了。然而最近又出现了与这个功能相关的一个bug。连续多次的意外让我对相关代码产生了怀疑。最后,我眼中望着桌上一堆装有不同iOS版本的iPhone和iPad,手里抚摸着如丝般顺滑硬件指数爆表的iPhone Xs,鬼魅般的灵感涌上心头。我突然想到了一个终极完美解决方案,以保证这些相关代码再也不会因为iOS SDK升级出问题了。
最终方案
我说服产品经理把这个功能去掉了。
作者:刘欣,微策略架构师。毕业于清华大学电子系,2007年加入微策略。参与过微策略多个产品的研发,包括可视化引擎、移动端应用。目前负责微策略管理工具以及REST服务器的研究开发工作。
声明:本文为作者投稿,版权归其所有。
【END】
热 文推 荐
你点的每个“在看”,我都认真当成了喜欢
领取专属 10元无门槛券
私享最新 技术干货