提出在iOS7和iOS8中均可使用的半透明viewcontroller

时间:2014-09-25 06:57:14

标签: ios ios7 ios8

我有以下代码在iOS7中完美运行。

[UIView animateWithDuration:0.5 animations:^(void) {
    self.view.alpha = 0.5;
    [self.navigationController.navigationBar setAlpha:0.3];

}]; //to make the background view controller semi-transparent
UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
[rootViewController setModalPresentationStyle:UIModalPresentationCurrentContext];
OverlayViewController *ctlr = [storyBoard instantiateViewControllerWithIdentifier:@"OverlayViewController"];
//present the OverlayViewController
[self presentViewController:ctlr animated:YES completion:nil];

然后我在后台视图控制器的viewWillAppear中有以下内容,将其视图恢复为完全不透明。

[UIView animateWithDuration:1.0 animations:^(void) {
    self.view.alpha = 1.0;
    [self.navigationController.view setAlpha:1.0];
}];

现在,对于iOS8,上面的代码没有将背景设置为半透明。 OverlayViewController环绕黑色。

我在网上发现,使用UIModalPresentationOverCurrentContext会产生预期的行为。它实际上确实如此,但背景视图控制器永远不会脱离视图层次结构(编辑以添加对此行为的引用:https://developer.apple.com/documentation/uikit/uimodalpresentationstyle)。因此,从不调用viewWillAppear,因此永远不会删除半透明度。

显然,我可以使用像使用NSNotificationCenter这样的黑客攻击并在删除OverlayViewController时触发通知,但感觉就像是一种迂回的方式来做一些简单的事情。还有其他方法可以优雅地实现这个目标吗?

推论问题:

1)如果UIModalPresentationOverCurrentContext是实现这一目标的唯一方法,那么我想知道我是否会被迫放置两个版本的代码以使其在iOS7和iOS8中都能正常工作。

2)显然,在早期版本的Xcode中无法识别新的枚举。那么,我的团队是否应该升级到Xcode 6以确保他们可以运行此代码,即使他们的其余工作仅以iOS7为中心?或者有没有办法告诉旧版本的Xcode忽略仅适用于iOS8的特定代码块?

3 个答案:

答案 0 :(得分:36)

您必须为iOS 7和iOS8处理两种配置。在这两种情况下,您都需要确保背景视图控制器不会脱离视图层次结构。这可以通过以下方式实现:

  1. 在iOS7上为呈现视图控制器设置modalPresentationStyle标记为UIModalPresentationCurrentContext。您需要确定谁是呈现视图控制器:如果您有多个容器视图控制器,则不一定是self.navigationController

  2. 在iOS8上为呈现的视图控制器设置modalPresentationStyle标记为UIModalPresentationOverCurrentContext。如果您正在使用故事板,请确保将故事板segue的演示文稿样式设置为Default,并在prepareForSegue方法中将目标视图控制器的演示样式设置为UIModalPresentationOverCurrentContext

  3. 现在回答你的推论:

    1)你需要有代码来处理iOS7和iOS8上的两种情况:

    定义一些宏以检查运行应用程序的版本号。例如,以下内容将:

    #define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
    #define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
    #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
    #define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
    #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
    

    2)显然,如果您的代码需要在iOS7和iOS8上编译,那么您的团队需要更新到最新版本的XCode“XCode 6.1”。

答案 1 :(得分:4)

在Swift for iOS 8.x中:

UIModalPresentationStyle.OverCurrentContext 设置为viewController 正在呈现 完成工作。

    func presentTransparentController(){
        var viewController = self.storyboard?.instantiateViewControllerWithIdentifier("ViewControllerNamed") as! ViewController

        // set to .OverCurrentContext
        viewController.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext

        // presents the view controller as usual
        self.presentViewController(viewController, animated: true, completion: nil)
    }

答案 2 :(得分:1)

根据@ Tiguero的回答,我创建了一个小类来解决问题。

@implementation UIViewController (Extensions)

- (void) presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
    if(SYSTEM_VERSION_LESS_THAN(@"8.0")) {
        self.parentViewController.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
    }else{
        viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
    }

    [self presentViewController:viewControllerToPresent animated:YES completion:completion];
}

@end

iOS7版本要求我对执行演示的控制器进行硬编码。