iOS 7: 隱藏的特性和解決之道
當 iOS7 剛發(fā)布的時候,全世界的蘋果開發(fā)人員都立馬嘗試著去編譯他們的app,接著再花上數(shù)月的時間來修復任何出現(xiàn)的故障,甚至重做app。這樣的結果,使得人們根本無暇去探究 iOS7 所帶來的新東西。一些明顯而細微的更新,比如說[NSArray firstObject],這個方法可追溯到 iOS4 時代,現(xiàn)在被提為公有API,除此之外,還有很多隱藏的特性等著我們?nèi)ネ诰颉?/p>本文引用地址:http://m.butianyuan.cn/article/201609/304760.htm
平滑淡入淡出動畫
我這里要討論的并非新的彈性動畫APIs 或者 UIDynamics,而是一些更細微的東西。CALayer增加了兩個新方法:allowsGroupOpacity和allowsEdgeAntialiasing?,F(xiàn)在,組不透明度(group opacity)不再是什么新鮮的東西了。iOS會多次使用存在于 Info.plist 中的鍵UIViewGroupOpacity并可在應用程序范圍內(nèi)啟用或禁用它。對于大多數(shù)apps而言,這(譯注:啟用)并非所期望的,因為它會降低整體性能。在 iOS7 中,用 SDK7 所鏈接的程序,這項屬性默認是啟用的。當它被啟用時,一些動畫將會變得不流暢,它也可以在layer層上被控制。
一個有趣的細節(jié),如果allowsGroupOpacity啟用的話,_UIBackdropView(在UIToolbar或者UIPopoverView中的背景視圖)不能對其模糊進行動畫處理,所以當你做一個alpha轉(zhuǎn)換時,你可能會臨時禁用這項屬性。因為這會降低動畫體驗,你可以回退到舊的方式然后在動畫期間臨時啟用shouldRasterize。別忘了設置適當?shù)膔asterizationScale,否則在retina的設備上這些視圖會成鋸齒狀。
如果你想要復制的 Safari 顯示所有選項卡時的動畫,那么邊緣抗鋸齒屬性將變得非常有用。
阻塞動畫
一個小但非常有用的新方法[UIView performWithoutAnimation:]。它是一個簡單的封裝,先檢查動畫當前是否啟用,然后禁止動畫,執(zhí)行塊語句,最后重新啟用動畫。一個需要說明的地方是,它并不會阻塞基于 CoreAnimation 的動畫。因此,不用急于將你的方法調(diào)用從:
[CATransaction begin];
[CATransaction setDisableActions:YES];
view.frame = CGRectMake(...);
[CATransaction commit];
替換為:
1
2
3[UIView performWithoutAnimation:^{
view.frame = CGRectMake(...);
}];
但是,絕大多數(shù)情況下這樣也能工作的很好,只要你不直接處理CALayers。
iOS7 中,我有很多代碼路徑(主要是 UITableViewCells)需要額外的保護,防止意外的動畫,例如,如果一個彈窗的大小調(diào)整了,那么同時顯示中的表視圖將因為高度的變化而加載新的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:,它會開始為你表中任意元素調(diào)用此方法,即便沒有可視對象,就比如其內(nèi)在的UIScrollView只是去獲取正確的contentSize。此前有一些變通方法,但都不好用。iOS7 中,蘋果公司終于承認這一問題,并添加tableView:estimatedHeightForRowAtIndexPath:,這個方法延遲了實際滾動時間成本的大部分。如果你不知道一個cell的大小,返回UITableViewAutomaticDimension即可。
對于節(jié)頭/尾(section headers/footers),現(xiàn)在也有類似的API了。
UISearchDisplayController
蘋果的 search controller 使用了新的技巧來簡化移動 search bar 到 navigation bar 的過程。啟用 displaysSearchBarInNavigationBar 就可以了(除非你還要用到 scope bar,我只能說你真不幸)。我倒是很喜歡這么做,但比較遺憾的是,iOS7 上的 UISearchDisplayController 貌似被摧殘的比較嚴重,尤其是iPad。蘋果公司看上去像是沒時間處理這個問題的樣子(原文:Apple seems to have run out of time),對于顯示的搜索結果并不會隱藏實際的表視圖。在 iOS7 之前,這并沒有問題,但是現(xiàn)在 searchResultsTableView 有一個透明的背景色,使它看上去相當糟糕。作為一種變通方法,你可以設置不透明色或者取道于富于技巧的手段來獲得你所期望的。關于這個控件會出現(xiàn)各種各樣的結果,當使用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中調(diào)用restoreOriginalTableView,否則會發(fā)送crash。
記住這是唯一的解決辦法;可能有不少激進的方法不替換視圖本身,但這個問題確實應該由蘋果公司來修復。(TODO: RADAR!)
評論