天天看點

定制Segue - OverlaySegue

背景:

  以前做的幾個項目,都會這樣的一些需求,定制ActionSheet/AlertView,彈出菜單,模态對話框,這些需求都有一個共同點,需要覆寫在源視圖上面。

1、一開始的思路當然是使用系統原生機制,如UIPopoverController,但研究過後發現,UIPopoverController不适用于iPhone,隻能在iPad等大屏機上使用,而且IOS9.0後,系統已經建議廢棄些類,用[UIViewController presentViewController:]代替其功随時能。

2、UIViewController presentViewController

IOS8後,将presentationStyle設定為UIModalPresentationOverCurrentContext後,完美替代Popover的功能。但是IOS7等舊版本呢,不能使用UIModalPresentationOverCurrentContext,但也有方法實作,方法就是将[UIApplication sharedApplication].keywindow.rootViewController的presentationStyle設定為UIModalPresentationCurrentContext。但有個瑕疵,present動畫沒了,dismiss動畫正常,通過各種途徑仍然找不到解決方案。

3、[UIViewController addChildViewController] [UIView addSubview]

直接操作目标視圖,優點是定制自由度高,動畫想怎麼弄怎麼弄。但使用過程中發現有幾個問題,如果VC是放在NavigationController裡面的,addSubview是加在誰上面呢? VC? NC? 加在目前VC上的話,産品想點選全屏空白區域都關閉彈窗,不好滿足。加在NavigationController或者app rootViewController上的話,收到推送消息了,要随時關閉目前界面跳轉到目标界面,不好實作

新思路 - UIModalPresentationCustom

總結了一下所需要的功能特性

1、便于使用

2、可定制動畫

3、可随時關閉

一個視圖建立出來後,直接presentViewController是最友善的;通過app rootViewContrller dismissViewControllerAnimated,就可以關掉模态彈窗。研究了UIViewController的頭檔案,找到了presentationStyle - UIModalPresentationCustom。

主要思路就是定制視圖彈出方式,但又不破壞模态視圖的特性

/**
 *  @class TVOverlaySegue
 *  浮層式彈出
 *  類似UIStoryboardPopoverSegue,目标視圖控制器彈出後,直接覆寫在源視圖上面,
 *  源視圖與目标視圖共存
 *  可将目标視圖背景設定為透明,則可透過目标視圖看到源視圖
 *  可在Storyboard中直接拖拽來建立連接配接,除了動畫形式,其行為與Present Modally完全一緻,目标視圖可通過dismissViewControllerAnimated關閉
 */
@interface TVOverlaySegue : UIStoryboardSegue

@end


@interface TVOverlaySegue () <UIViewControllerTransitioningDelegate>

@end

@implementation TVOverlaySegue

- (id<UIViewControllerTransitioningDelegate>)transitioningDelegate
{
    NSMutableDictionary *data = [self.destinationViewController tv_overlayData];
    id <UIViewControllerTransitioningDelegate> delegate = data[@"TransitioningDelegate"];
    if (!delegate)
    {
        delegate = [[TVOverlayTransitioningDelegate alloc] init];
        data[@"TransitioningDelegate"] = delegate;
    }
    return delegate;
}

- (void)perform
{
    self.destinationViewController.transitioningDelegate = self.transitioningDelegate;
    self.destinationViewController.modalPresentationStyle = UIModalPresentationCustom;
    
    [self.sourceViewController presentViewController:self.destinationViewController animated:YES completion:NULL];
}           

通過擴充Segue,非常便于Storyboard中使用,Ctrl + Drag即可建立,并且Unwind Segue都是天然支援的。

最後附上源碼,如有問題歡迎提出交流

https://github.com/maplelover/OverlaySegue