如上篇文章所说,3D Touch 主要分成三个模块: Home Actions, Peek & Pop, Force Properties。上篇文章中总结了 Home Actions的相关知识点以及如何接入该功能。本文将用来介绍Peek & Pop 的相关知识点。

在给你的app接入peeking and poping 的功能之前,需要先了解该操作的三个属性, peeking, preview actions, poping。如下图所示:

peek_and_pop

用户在 Peeking 图片,视频,网页等内容的时候,能够在不去加载全部内容的情况下获取到更多详细的内容。

##PEEKING

当用户对某个view做peeking操作时,程序会展现给用户相对应内容的快照。Peek 操作是 3DTouch 中实现起来相对比较复杂的模块。Peek and Pop API 中有一个 UIViewControllerPreviewingDelegate,给指定的view需要注册这个delegate,就可以接收到系统回调过来的3D Touch事件。

override func viewDidLoad() {
    super.viewDidLoad()

    /*  
        Register for `UIViewControllerPreviewingDelegate` to enable
        "Peek" and "Pop".
        The view controller will be automatically unregistered when it is
        deallocated.
    */
    registerForPreviewingWithDelegate(self, sourceView: view)
}

这里有一点需要注意,我们可以在一个 view Controller 中,给多个view注册 Previewing Delegate ,但是我们不能反复去注册同一个view。

“You can designate more than one source view for a single registered view controller, but you cannot designate a single view as a source view more than once.”

Peek的操作过程可以分解成下面三个步骤:

peek_and_pop_2

Peek的系统回调函数会提供一个关于 source view的context,以及 touch事件的point。以sourceView为 collectionView为例,回调函数中我们需要处理以下三件事情:

  • (1) 根据 location 找到被 peeked 的 cell,以及cell的 NSIndexPath
  • (2) 设置 previewingContext 的 sourceRect 大小
  • (3) alloc 一个 PreViewController,并设置背景图片,title之类的, 然后返回这个 PreviewController

UICOLLECTIONVIEW 代码片段

override func viewDidLoad() {
    super.viewDidLoad()

    registerForPreviewingWithDelegate(self, sourceView: tableView)
}

func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
    guard let indexPath = collectionView?.indexPathForItemAtPoint(location) else { return nil }
    
    guard let cell = collectionView?.cellForItemAtIndexPath(indexPath) else { return nil }
    
    guard let detailVC = storyboard?.instantiateViewControllerWithIdentifier("DetailViewController") as? DetailViewController else { return nil }
    
    let photo = photos[indexPath.row]
    detailVC.photo = photo
    
    detailVC.preferredContentSize = CGSize(width: 0.0, height: 300)
    
    previewingContext.sourceRect = cell.frame
    
    return detailVC
}

UIPREVIEWACTIONITEMS

当用户在 PreViewing Controller 的界面,手指往上推,会从屏幕底部弹出一个类似 actionsheet 的界面,这个是 UIPreviewActions。那如何给指定的 preViewController 自定义这些 UIPreviewActions? 方法很简单,override UIViewController 中的 preViewActionItems() 方法,在该方法中定义好 actionItems 的数组就好了:

override func previewActionItems() -> [UIPreviewActionItem] {

    let likeAction = UIPreviewAction(title: "Like", style: .Default) { (action, viewController) -> Void in
        print("You liked the photo")
    }

    let deleteAction = UIPreviewAction(title: "Delete", style: .Destructive) { (action, viewController) -> Void in
        print("You deleted the photo")
    }

    let groupAction = UIPreviewActionGroup (title: "Group", style: .Default, actions: [likeAction, deleteAction])
    return [likeAction, deleteAction, groupAction]

}

另外苹果还提供了 UIPreviewActionGroup,顾名思义就是把几个UIPreviewActionItem操作放到一起,组成一个组。

POPPING

poping 操作处理起来相对简单。在回调函数中

func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) {
    //Here's where you commit (pop)
}

我们需要根据preViewingContext来确定poping的时候需要commit的ViewController就好了。

WEBVIEW PEEK AND POP

UIWebViewWKWebview 支持 Peek&Pop就很简单了:

webView.allowsLinkPreview = true

##结语

以上。