新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > iOS 7: 隐藏的特性和解决之道

iOS 7: 隐藏的特性和解决之道

作者: 时间:2016-09-12 来源:网络 收藏

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

本文引用地址:https://www.eepw.com.cn/article/201609/304760.htm

平滑淡入淡出动画

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

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

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

阻塞动画

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

[CATransaction begin];

[CATransaction setDisableActions:YES];

view.frame = CGRectMake(...);

[CATransaction commit];

替换为:

1

2

3[UIView performWithoutAnimation:^{

view.frame = CGRectMake(...);

}];

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

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

(void)layoutSubviews

{

// Otherwise the popover animation could leak into our cells on iOS 7 legacy mode.

[UIView performWithoutAnimation:^{

[super layoutSubviews];

_renderView.frame = self.bounds;

}];

}

处理长表视图

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工作的:

(void)restoreOriginalTableView

{

if (PSPDFIsUIKitFlatMode() self.originalTableView) {

self.view = self.originalTableView;

}

}

- (UITableView *)tableView

{

return self.originalTableView ?: [super tableView];

}

- (void)searchDisplayController:(UISearchDisplayController *)controller

didShowSearchResultsTableView:(UITableView *)tableView

{

// HACK: iOS 7 requires a cruel workaround to show the search table view.

if (PSPDFIsUIKitFlatMode()) {

if (!self.originalTableView) self.originalTableView = self.tableView;

self.view = controller.searchResultsTableView;

controller.searchResultsTableView.contentInset = UIEdgeInsetsZero; // Remove 64 pixel gap

}

}

- (void)searchDisplayController:(UISearchDisplayController *)controller

didHideSearchResultsTableView:(UITableView *)tableView

{

[self restoreOriginalTableView];

}

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

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


上一页 1 2 3 4 下一页

关键词:

评论


相关推荐

技术专区

关闭