3D Touch 有一个 Peek and Pop 功能,简单的说就是用力按可以预览即将载入的 view controller,再按下去将其变为全屏。前几天给 Expense 实现了,在这里记录一下。
先来看一下 Expense 的效果:
典型的 Peek and Pop 在 peek 时载入 view controller,在 pop 时将 view controller push 到 navigation stack 中。这种 Peek and Pop 在两个阶段共享同一个 view controller,实现起来比较简单,可以参见 Little Bites of Cocoa 上的这篇文章 。
而 Expense 希望在 pop 时将 view controller 作为 modal 弹出,这样就不能使用 showViewController:sender:
了(这个方法只能把 view controller 推入 navigation stack)。也就是说,要为 peek 和 pop 使用不同的 view controller。带来的额外好处是可以很简单地为 preview 使用完全不同的 UI。
Expense 在 preview 阶段就用了完全不同的 UI:
实现起来也不复杂,首先将 table view 注册为支持 3D Touch:
[ self registerForPreviewingWithDelegate : self sourceView : self . tableView ];
然后实现 UIViewControllerPreviewingDelegate 的两个方法就可以了:
#pragma mark - UIViewControllerPreviewingDelegate
- ( UIViewController * ) previewingContext :( id < UIViewControllerPreviewing > ) previewingContext viewControllerForLocation :( CGPoint ) location
{
NSIndexPath * indexPath = [ self . tableView indexPathForRowAtPoint : location ];
UITableViewCell * cell = [ self . tableView cellForRowAtIndexPath : indexPath ];
if ( ! cell ) {
return nil ;
}
// 保存 index path,在 performSegueWithIdentifier:sender: 里会用到
self . previewingIndexPath = indexPath ;
TYKPreviewViewController * previewVC = [[ TYKPreviewViewController alloc ] initWithNibName : @"TYKPreviewViewController" bundle : nil ];
TYKTaiyaki * taiyaki = [ self . fetchedResultsController objectAtIndexPath : indexPath ];
previewVC . taiyaki = taiyaki ;
previewVC . preferredContentSize = CGSizeMake ( 0 , 180 );
previewingContext . sourceRect = cell . frame ;
return previewVC ;
}
- ( void ) previewingContext :( id < UIViewControllerPreviewing > ) previewingContext commitViewController :( UIViewController * ) viewControllerToCommit
{
// 在按下去后,用 performSegueWithIdentifier:sender: 弹出 view controller
[ self performSegueWithIdentifier : @"Edit" sender : self ];
}
最后,Expense 真的,真的,快要发布了。:)