objc系列译文(5.6):iOS7 的隐藏特性和解决之道

416 查看

【感谢 @小清新_style 的热心翻译(原稿链接)。如果其他朋友也有不错的原创或译文,可以尝试提交到伯乐在线。】

 

当 iOS7 刚发布的时候,全世界的苹果开发人员都立马尝试着去编译他们的app,接着再花上数月的时间来修复任何出现的故障,甚至重做app。这样的结果,使得人们根本无暇去探究 iOS7 所带来的新东西。一些明显而细微的更新,比如说[NSArray firstObject],这个方法可追溯到 iOS4 时代,现在被提为公有API,除此之外,还有很多隐藏的特性等着我们去挖掘。

 

平滑淡入淡出动画

我这里要讨论的并非新的弹性动画APIs 或者 UIDynamics,而是一些更细微的东西。CALayer增加了两个新方法:allowsGroupOpacityallowsEdgeAntialiasing。现在,组不透明度(group opacity)不再是什么新鲜的东西了。iOS会多次使用存在于 Info.plist 中的键UIViewGroupOpacity并可在应用程序范围内启用或禁用它。对于大多数apps而言,这(译注:启用)并非所期望的,因为它会降低整体性能。在 iOS7 中,用 SDK7 所链接的程序,这项属性默认是启用的。当它被启用时,一些动画将会变得不流畅,它也可以在layer层上被控制。

一个有趣的细节,如果allowsGroupOpacity启用的话,_UIBackdropView(在UIToolbar或者UIPopoverView中的背景视图)不能对其模糊进行动画处理,所以当你做一个alpha转换时,你可能会临时禁用这项属性。因为这会降低动画体验,你可以回退到旧的方式然后在动画期间临时启用shouldRasterize。别忘了设置适当的rasterizationScale,否则在retina的设备上这些视图会成锯齿状。

如果你想要复制的 Safari 显示所有选项卡时的动画,那么边缘抗锯齿属性将变得非常有用。

 

阻塞动画

一个小但非常有用的新方法[UIView performWithoutAnimation:]。它是一个简单的封装,先检查动画当前是否启用,然后禁止动画,执行块语句,最后重新启用动画。一个需要说明的地方是,它并不会阻塞基于 CoreAnimation 的动画。因此,不用急于将你的方法调用从:

替换为:

但是,绝大多数情况下这样也能工作的很好,只要你不直接处理CALayers。

iOS7 中,我有很多代码路径(主要是 UITableViewCells)需要额外的保护,防止意外的动画,例如,如果一个弹窗的大小调整了,那么同时显示中的表视图将因为高度的变化而加载新的cell。我通常的做法是将整个 layoutSubviews 的代码包扎到一个动画块中:

处理长表视图

UITableView 非常快速高效,除非你开始使用tableView:heightForRowAtIndexPath:,它会开始为你表中任意元素调用此方法,即便没有可视对象,就比如其内在的UIScrollView只是去获取正确的contentSize。此前有一些变通方法,但都不好用。iOS7 中,苹果公司终于承认这一问题,并添加tableView:estimatedHeightForRowAtIndexPath:,这个方法延迟了实际滚动时间成本的大部分。如果你不知道一个cell的大小,返回UITableViewAutomaticDimension即可。

对于节头/尾(section headers/footers),现在也有类似的API了。

 

UISearchDisplayController

苹果的 search controller 使用了新的技巧来简化移动 search bar 到 navigation bar 的过程。启用 displaysSearchBarInNavigationBar 就可以了(除非你还要用到 scope bar,我只能说你真不幸)。我倒是很喜欢这么做,但比较遗憾的是,iOS7 上的 UISearchDisplayController 貌似被摧残的比较严重,尤其是iPad。苹果公司看上去像是没时间处理这个问题的样子(原文:Apple seems to have run out of time),对于显示的搜索结果并不会隐藏实际的表视图。在 iOS7 之前,这并没有问题,但是现在 searchResultsTableView 有一个透明的背景色,使它看上去相当糟糕。作为一种变通方法,你可以设置不透明色或者取道于富于技巧的手段来获得你所期望的。关于这个控件会出现各种各样的结果,当使用displaysSearchBarInNavigationBar时甚至不会展示搜索表视图。

你的结果可能有所不同,但我是使用了一些手段来让displaysSearchBarInNavigationBar工作的:

这里,别忘了在viewWillDisappear中调用restoreOriginalTableView,否则会发送crash。

记住这是唯一的解决办法;可能有不少激进的方法不替换视图本身,但这个问题确实应该由苹果公司来修复。(TODO: RADAR!)

 

分页

UIWebView 使用了新的技巧来自动分页带paginationMode的网站。有一大堆与此功能相关的新属性: