我有以下代码在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的特定代码块?
答案 0 :(得分:36)
您必须为iOS 7和iOS8处理两种配置。在这两种情况下,您都需要确保背景视图控制器不会脱离视图层次结构。这可以通过以下方式实现:
在iOS7上为呈现视图控制器设置modalPresentationStyle
标记为UIModalPresentationCurrentContext
。您需要确定谁是呈现视图控制器:如果您有多个容器视图控制器,则不一定是self.navigationController
。
在iOS8上为呈现的视图控制器设置modalPresentationStyle
标记为UIModalPresentationOverCurrentContext
。如果您正在使用故事板,请确保将故事板segue的演示文稿样式设置为Default,并在prepareForSegue
方法中将目标视图控制器的演示样式设置为UIModalPresentationOverCurrentContext
。
现在回答你的推论:
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版本要求我对执行演示的控制器进行硬编码。