2015年10月26日 星期一

iOS 9 3D Touch simple Demo

隨著iPhone 6s現世,新功能也隨之而來, 其中對於開發者來說影響最深的有兩件事,第一是3D Touch應用,以及iPad Air的子母畫面應用,本篇主要針對3D Touch來做介紹.



APP內部的3D Touch

3D Touch是透過按壓力道不同來呈現不同的畫面,在Apple自己的定義中分為「peek」以及「pop」兩種狀態,程式上對應peek是需要回應一個ViewController,而pop卻不一定需要做任何動作,它允許你自由反應pop事件.以下將根據Simple Demo介紹3D Touch

首先我們來做一個情境假設:
情境1. 現在有A & B兩個頁面, 然後要透過A頁面執行3D Touch時顯示B頁面
情境2. peek & pop 事件要做不一樣的效果.

首先我們要在A頁面的ViewController加入 UIViewControllerPreviewingDelegate ,讓我們來看看這個Delegate裡面有什麼吧:
@available(iOS 9.0, *)
public protocol UIViewControllerPreviewingDelegate : NSObjectProtocol {
    
    // If you return nil, a preview presentation will not be performed
    // peek event
    @available(iOS 9.0, *)
    public func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?
    
    // pop event
    @available(iOS 9.0, *)
    public func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController)
}

從上面的Code中我們可以看到有兩個Func,這兩個分別對應peek&pop事件,從註解中可以看到peek event是有return ViewController的, 而pop事件是沒有的,而這兩個事件如果你都是去呼叫一個ViewController並且希望呈現他的話,在peek event中只要return你要的ViewController就好, 而pop event則看你想要用present mode  還是 push mode. 就按照一般頁面跳轉的方式去做就好,範例Code如下:
    //MARK: UIViewControllerPreviewingDelegate - 3DTouch Using.
    func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) {
        
        let index = (previewingContext.sourceView as! DefaultCell).indexPath
        let page = getPage("ImageViewController") as! ImageViewController;
        page.imageName = self.images[index.row];
        self.navigationController?.pushViewController(page, animated: true);
        
    }
    
    
    func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
        
        let index = (previewingContext.sourceView as! DefaultCell).indexPath
        let page = getPage("ImageViewController") as! ImageViewController;
        page.imageName = self.images[index.row];
        page.isPreview = true;
        return page;
    }


稍微解釋一下上面的Code, func getPage(String)就只是去抓到要的ViewController而已,沒什麼特別的,比較值得注意的是我在ImageViewController中加入了isPreview變數,用於判斷現在是peek event or pop event,來決定顯示的畫面到底是如何,另外一點是我的觸發SourceView為cell, 而為了參數傳遞,特別在製作一個DetaulCell Class, 主要是繼承了UITableViewCell,並且建立一個變數 indexPath: NSIndexPath,這樣就可以透過它來取得參數了,詳細的Code可以在Simple Code看到,在此不多作說明了.

以上這些都是Delegate的event,Delegate如果沒有註冊的話那上面的東西也是沒作用的,因此我們需要在ViewController當中去註冊UIViewControllerPreviewingDelegate,而註冊UIViewControllerPreviewingDelegate如下:

      if #available(iOS 9.0, *) {
            self.registerForPreviewingWithDelegate(self, sourceView: cell);
      }


如果你點進去func裡面的話你就可以看到:
      public func registerForPreviewingWithDelegate(delegate: UIViewControllerPreviewingDelegate, sourceView: UIView)

delegate當然就是指自己本身嘛,如果你沒有額外需求的話,而sourceView則是你想要觸發3D Touch的UIView,你可以是self.view本身,也可以是某個UIButton,甚至是UILabel,並且一個ViewController中並不只限制你註冊一個sourceView,你可以註冊多個,像我的範例中就是每個DefaultCell都註冊.而只要是註冊的sourceView就會產生3D Touch的效果.


如果上面動作都做完的話,基本上你App內部的3D Touch是已經做好了,而你如果想要在3D Touch上面加入action的話,則是要再被呼叫的頁面中加入,利用Simple Demo中是ImageViewController被呼叫,所以我們在ImageViewController加入以下的Code:
    override func previewActionItems() -> [UIPreviewActionItem] {
        
        let items = [
            UIPreviewAction(title: "View", style: .Default, handler: { (actoin, controller) -> Void in
                print("View action handler");
            })
        ]
        
        return items;
    }



AppIcon上的3D Touch

如果要設定AppIcon上的menu list有兩種方式,一種是利用plist做到,可以在plist中加入這段:


 UIApplicationShortcutItems
 
  
   UIApplicationShortcutItemType
   com.test.static1
   UIApplicationShortcutItemTitle
   Static Shortcut
   UIApplicationShortcutItemSubtitle
   available at launch
   UIApplicationShortcutItemIconFile
   iCon1
  
 
另外一種是直接設定 application.shortcutItems, 這是一個iOS9新多出來的屬性,以下是示範:
let items = [
            UIApplicationShortcutItem(type: "List", localizedTitle: "Image List"),
            UIApplicationShortcutItem(type: "田馥甄", localizedTitle: "田馥甄"),
            UIApplicationShortcutItem(type: "A-Lin", localizedTitle: "A-Lin"),
            UIApplicationShortcutItem(type: "王心凌", localizedTitle: "王心凌"),
            UIApplicationShortcutItem(type: "林依晨", localizedTitle: "林依晨")
            
        ];
        
        UIApplication.sharedApplication().shortcutItems = items;


以上是設定的部分,而Delegate部分則是在AppDelegate中新增了以下這個Delegate:
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
        switch(shortcutItem.type) {
        case "List":
            // do something you want.
           
         case "田馥甄":
            // do something you want.

        case "林依晨":
            // do something you want.

        default:
            break;
            
        }
        
        
    }

透過這個func可以捕捉到使用者觸發的AppIcon 3D Touch事件,那就可以去做你想要做的事情拉!


實際效果圖

AppIcon上的menu list



3D Touch trigger



3D Touch  peek event.



3D Touch  group action



3D Touch  pop event.

參考資料:
Adopting 3D Touch on iPhone


沒有留言:

張貼留言