“从视图控制器”在使用uiviewcontrollercontexttransfer时消失

时间:2021-01-24 10:09:14

I got one problem and i have described it below.

我有一个问题,我已经在下面描述过了。

I am using UIViewControllerContextTransitioning for custom transitions.

我正在为自定义转换使用uiviewcontrollercontexttransfer。

I have 2 view controllers , first view controller and second view controller.

我有两个视图控制器,第一视图控制器和第二视图控制器。

Now i want to add secondview controller on first view controller with animation. I have achieved it, now I have secondview controller transparent , so we can see first view controller below secondview controller.

现在我想在第一个视图控制器上添加第二个视图控制器。我已经实现了,现在我有了二视图控制器透明的,所以我们可以在二视图控制器下面看到第一视图控制器。

But i am not able to see first view controller , and i can see only black screen below secondview controller.

但是我看不到第一视图控制器,我只能看到第二视图控制器下面的黑屏。

Here is the code.

这是代码。

-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    self.transitionContext = transitionContext;
    if(self.isPresenting){
        [self executePresentationAnimation:transitionContext];
    }
    else{
       [self executeDismissalAnimation:transitionContext];
    }
  }

-(void)executePresentationAnimation:(id<UIViewControllerContextTransitioning>)transitionContext{
     UIView* inView = [transitionContext containerView];
     UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

     UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

     CGRect offScreenFrame = inView.frame;
     offScreenFrame.origin.y = inView.frame.size.height;
     toViewController.view.frame = offScreenFrame;

    toViewController.view.backgroundColor = [UIColor clearColor];
    fromViewController.view.backgroundColor = [UIColor clearColor];
    inView.backgroundColor = [UIColor  clearColor];
    [inView insertSubview:toViewController.view aboveSubview:fromViewController.view];
     // [inView addSubview:toViewController.view];
    CFTimeInterval duration = self.presentationDuration;
    CFTimeInterval halfDuration = duration/2;

    CATransform3D t1 = [self firstTransform];
    CATransform3D t2 = [self secondTransformWithView:fromViewController.view];

    [UIView animateKeyframesWithDuration:halfDuration delay:0.0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{

    [UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:0.5f animations:^{
        fromViewController.view.layer.transform = t1;
    }];

    [UIView addKeyframeWithRelativeStartTime:0.5f relativeDuration:0.5f animations:^{
        fromViewController.view.layer.transform = t2;
    }];
    } completion:^(BOOL finished) {
    }];


    [UIView animateWithDuration:duration delay:(halfDuration - (0.3*halfDuration)) usingSpringWithDamping:0.7f initialSpringVelocity:6.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
        toViewController.view.frame = inView.frame;
    } completion:^(BOOL finished) {
        [self.transitionContext completeTransition:YES];
    }];
}

When [self.transitionContext completeTransition:YES]; called, suddenly the first view controller disappears and black screen displays below second view controller.

当自我。transitionContext completeTransition:是的);调用时,第一个视图控制器突然消失,第二个视图控制器下面显示黑屏。

Does any one have idea ? Thanks.

有人知道吗?谢谢。

15 个解决方案

#1


94  

I was having the same problem here – looks like a bug in iOS 8. I've filed a radar.

我在这里遇到了同样的问题——看起来像是iOS 8中的一个bug。我提出了雷达。

I used Reveal to inspect the view hierarchy after the screen goes black. The key UIWindow is completely empty – no view hierarchy at all!

在屏幕变黑后,我使用了显示来检查视图层次结构。关键的UIWindow是完全空的——完全没有视图层次结构!

“从视图控制器”在使用uiviewcontrollercontexttransfer时消失

I played around a bit and it looks like there is an easy workaround, for simple cases. You can just re-add the toViewController's view as a subview of the key window's:

我尝试了一下,看起来有一个简单的解决方案。你可以重新添加toViewController的视图作为键窗口的子视图:

transitionContext.completeTransition(true)
UIApplication.sharedApplication().keyWindow!.addSubview(toViewController.view)

I've checked and the key window's rootViewController is still correctly set, so that's fine. I'm not sure what would happen if you presented your controller from within an already presented modal controller, so for more complex cases, you'll have to experiment around.

我已经检查过了,关键窗口的rootViewController仍然正确设置,所以没关系。我不确定如果你在一个已经展示过的模态控制器中展示你的控制器会发生什么,所以对于更复杂的情况,你必须进行实验。

#2


67  

I feel like the reasoning behind this should be explained better.

我觉得这背后的原因应该得到更好的解释。

The view disappears because you take out the presenting view controller's view out of its original location (view hierarchy), put it inside the containerView that your animator provides but never returns it back after the animation has finished. So that view controller's view is removed with its superview (containerView) from the window completely.

视图之所以消失,是因为您将呈现视图控制器的视图从其原始位置(视图层次结构)中取出,并将其放入动画师提供的containerView中,但动画完成后永不返回。这样视图控制器的视图就会被它的超视图(containerView)从窗口中删除。

In iOS 7 the system always returned view controllers' views that are involved in the presentation (presenting and presented) to their original places after the transition has finished animating automatically. That no longer happens for some presentation styles in iOS 8.

在ios7系统中,在转换完成自动动画后,系统总是将视图控制器的视图返回到它们的原始位置(呈现和呈现)。在iOS 8中,这种情况不再发生。

The rule is very simple: the animator should only manipulate the presenting view controller's view if that view controller's view is going to be hidden (removed from the view hierarchy) completely by the end of transition. In other words it means that after the initial presentation animation finishes only the presented view controller's view will be visible and not the presenting view controller's view. For example if you set presented view controller's view's opacity to 50% and use UIModalPresentationFullScreen you will not be able to see presenting view controller's view underneath the presented but if you use UIModalPresentationOverFullscreen - you will (UIPresentationController's shouldRemovePresentersView method is responsible for specifying that).

规则非常简单:如果视图控制器的视图在转换结束时完全隐藏(从视图层次结构中删除),动画器只应该操作呈现视图控制器的视图。换句话说,它意味着在初始表示动画完成后,只有显示视图控制器的视图是可见的,而不是显示视图控制器的视图。例如,如果你将显示视图控制器的不透明度设置为50%并使用UIModalPresentationFullScreen你将不能看到显示视图控制器的视图在显示视图下面,但是如果你使用UIModalPresentationOverFullscreen你会(UIPresentationController的shouldremovepressview方法负责指定)。

Why not allow the animator manipulate the presenting view controller's view at all times? First of all, if the presenting view controller's view is going to stay visible after the animation finishes during the whole presentation life cycle there is no need to animate it at all — it just stays where it is. Second, if the ownership for that view controller is transferred to the presentation controller, the presentation controller will most likely not know how to layout that view controller's view when needed for example when the orientation changes, but the original owner of the presenting view controller does.

为什么不让动画师一直操作呈现视图控制器的视图呢?首先,如果表示视图控制器的视图在整个表示生命周期中动画完成后仍然可见,那么就根本不需要对它进行动画处理——它只是停留在原来的位置。第二,如果该视图控制器的所有权被转移到表示控制器,表示控制器很可能不知道在需要时如何布局该视图控制器的视图,当方向发生变化时,但是present视图控制器的原始所有者会这样做。

In iOS 8 viewForKey: method was introduced to get views that the animator manipulates. First, it helps to follow the rule described above by returning nil whenever the animator should not touch the view. Second, it may return a different view for the animator to animate. Imagine that you are implementing a presentation similar to form sheet. In this case you would want to add some shadow or decoration around the presented view controller's view. The animator will animate that decoration instead and the presented view controller's view will be a child of the decoration.

在ios8 viewForKey:中引入了获取动画师操作的视图的方法。首先,当动画师不应该触碰视图时,返回nil,这有助于遵循上面描述的规则。其次,它可能会返回一个不同的视图给动画师。假设您正在实现一个类似于表单表的表示。在这种情况下,您可能希望在呈现的视图控制器的视图周围添加一些阴影或修饰。动画师会将那个装饰动画化,而呈现的视图控制器的视图将是装饰的子元素。

viewControllerForKey: doesn't go away, it can still be used if a direct access to view controllers is needed but the animator should not make any assumptions about the views it needs to animate.

viewControllerForKey:不会消失,如果需要直接访问视图控制器,仍然可以使用它,但是动画师不应该对要动画的视图做任何假设。

There are several things you can do to correctly fix an issue with a disappearing presenting view controller's view when you explicitly place it inside the animator's container view:

当您显式地将视图放入动画师的容器视图中时,您可以通过以下几项来正确地修复正在消失的显示视图控制器视图的问题:

  1. If do not need to animate the presenting view controller's view, use viewForKey: to get views to animate instead of reaching out to view controller's views directly. viewForKey: may return nil or even completely different views.

    如果不需要动画显示视图控制器的视图,请使用viewForKey:获取视图动画,而不是直接访问视图控制器的视图。viewForKey:可能返回nil,甚至完全不同的视图。

  2. If you want to animate the presenting view controllers's view you should consider using UIModalPresentationFullScreen style or continue using UIModalPresentationCustom and implement your own subclass of UIPresentationController with shouldRemovePresentersView returning YES. In fact, the implementation of this method is the main difference between internal presentation controllers defined by UIModalPresentationFullScreen and UIModalPresentationCustom styles apart from the fact that the latter allows you to use custom presentation controllers.

    如果你想要激活呈现视图控制器的视图你应该考虑使用UIModalPresentationFullScreen样式或者继续使用UIModalPresentationCustom实现你自己的UIPresentationController的子类用shouldremovepresentsview返回YES。实际上,这个方法的实现是UIModalPresentationFullScreen定义的内部表示控制器和UIModalPresentationCustom风格之间的主要区别,除了后者允许您使用自定义表示控制器之外。

  3. In all other rare cases you will have to return the presenting view controller's view to its original location as other answers suggested.

    在所有其他罕见的情况下,您将不得不像其他答案所建议的那样将呈现视图控制器的视图返回到其原始位置。

#3


66  

In iOS 8, you must manipulate the views returned by viewForKey: instead of the .view property of the view controllers returned by viewControllerForKey:. This isn't particularly clear from the beta documentation, but if you look into the source for UIViewControllerTransitioning.h you'll see this comment above viewControllerForKey::

在ios8中,必须操作viewForKey返回的视图:而不是viewControllerForKey返回的视图控制器的.view属性:。这在beta文档中并不是特别清楚,但是如果您查看uiviewcontrollertransition的源代码的话。h你会看到以上viewControllerForKey:

// Currently only two keys are defined by the
// system - UITransitionContextToViewControllerKey, and
// UITransitionContextFromViewControllerKey.
// Animators should not directly manipulate a view controller's views and should
// use viewForKey: to get views instead.
- (UIViewController *)viewControllerForKey:(NSString *)key;

So instead of adjusting frames etc of toViewController.view, use the return value of [transitionContext viewForKey:UITransitionContextToViewKey].

不是调整toViewController的帧等等。查看,使用[transitionContext viewForKey:UITransitionContextToViewKey]的返回值。

If your app needs to support iOS7 and/or Xcode 5, then you can use a simple category method on UIViewController like the following:

如果您的应用程序需要支持iOS7和/或Xcode 5,那么您可以在UIViewController上使用一个简单的类别方法如下:

- (UIView *)viewForTransitionContext:(id<UIViewControllerContextTransitioning>)transitionContext
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
    if ([transitionContext respondsToSelector:@selector(viewForKey:)]) {
        NSString *key = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey] == self ? UITransitionContextFromViewKey : UITransitionContextToViewKey;
        return [transitionContext viewForKey:key];
    } else {
        return self.view;
    }
#else
    return self.view;
#endif
}

Then, get your toViewController and fromViewController as usual, but get the views using [toViewController viewForTransitionContext:transitionContext].

然后,像往常一样获取toViewController和fromViewController,但是使用[toViewController viewForTransitionContext:transitionContext]获取视图。

Edit: There appears to be a bug, where the presenting view controller's view is nil when returned from viewForKey, which prevents you from making modal transitions that animate the presenting view at all (such as sliding off, or flip-horizontal). I filed a bug for iOS8 at rdar://17961976 (http://openradar.appspot.com/radar?id=5210815787433984). Also see the sample project at http://github.com/bcherry/TransitionBug

编辑:似乎有一个bug,当从viewForKey返回时,呈现视图控制器的视图为nil,这阻止您进行模式转换,从而使呈现视图完全活跃(例如滑动或水平切换)。我在rdar://17961976 (http://openradar.appspot.com/radar?id=5210815787433984)为iOS8提交了一个bug。还可以在http://github.com/bcherry/TransitionBug上看到示例项目

Edit 2: Thanks to graveley for the suggestion, using UIModalPresentationFullScreen fixes the issue. Perhaps this is not a bug. Apple may intend that UIModalPresentationCustom only modifies the view of the incoming modal. If you want to modify the outgoing view, you need to guarantee full screen presentation of the new view? In any case, you should use viewForKey and UIModalPresentationFullScreen.

编辑2:感谢graveley的建议,使用UIModalPresentationFullScreen解决这个问题。也许这不是一个错误。苹果可能打算UIModalPresentationCustom只修改传入模式的视图。如果要修改传出视图,需要保证新视图的全屏显示?无论如何,您应该使用viewForKey和UIModalPresentationFullScreen。

#4


22  

Not setting modalPresentationStyle to UIModalPresentationCustom fixed the issue for me.

不设置modalPresentationStyle到UIModalPresentationCustom为我解决这个问题。

In other words, leaving at the default of UIModalPresentationFullScreen instead of specifying UIModalPresentationCustom fixed the disappearing view issue. Note the UIViewControllerTransitioningDelegate protocol still seems to be followed even when leaving this at the default. If i recall correctly, once upon a time UIModalPresentationCustom was a requirement.

换句话说,在UIModalPresentationFullScreen的默认状态下离开,而不是指定UIModalPresentationCustom修复消失的视图问题。注意,UIViewControllerTransitioningDelegate协议似乎仍然遵循,即使在默认设置下。如果我没记错的话,曾几何时UIModalPresentationCustom是一个需求。

Works so far, have only tried this for non-interactive animations.

到目前为止,作品只尝试过非交互式动画。

#5


12  

I've found this extremely useful answer in a related thread by Lefteris: https://*.com/a/27165723/3709173

我在一个相关的线程中找到了这个非常有用的答案:https://*.com/a/27165723/3709173。

To sum it up:

总结一下:

  1. set modalPresentationStyle to .Custom
  2. 设置modalPresentationStyle .Custom
  3. subclass UIPresentationController, override shouldRemovePresentersView (with NO)
  4. UIPresentationController的子类,覆盖shouldremovepressview(没有)
  5. override presentationControllerForPresentedViewController in your TransitionDelegate class and return your custom UIPresentationController
  6. 在TransitionDelegate类中重写presentationControllerForPresentedViewController并返回自定义的UIPresentationController。

+1 in your custom transition, don't add toView when the dismissal animation is happening.

+1在你的自定义转换中,当解雇动画发生时,不要添加toView。

Demonstrated here:

证明:

https://www.dropbox.com/s/7rpkyamv9k9j18v/CustomModalTransition.zip?dl=0 without any hacks! it's like magic! :)

https://www.dropbox.com/s/7rpkyamv9k9j18v/CustomModalTransition.zip?dl = 0,没有任何黑客!它就像魔法!:)

#6


8  

In iOS 8, you need create a UIPresentationController and implement the method below, in the UIViewControllerTransitioningDelegate.

在ios8中,需要创建一个UIPresentationController并在UIViewControllerTransitioningDelegate中实现下面的方法。

- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source;

Asks your delegate for the custom presentation controller to use for managing the view hierarchy when presenting a view controller.

请委托自定义表示控制器在显示视图控制器时用于管理视图层次结构。

Return Value:

返回值:

The custom presentation controller for managing the modal presentation.

用于管理模态表示的自定义表示控制器。

Discussion:

讨论:

When you present a view controller using the UIModalPresentationCustom presentation style, the system calls this method and asks for the presentation controller that manages your custom style. If you implement this method, use it to create and return the custom presentation controller object that you want to use to manage the presentation process.

当您使用UIModalPresentationCustom表示样式呈现一个视图控制器时,系统会调用这个方法并请求管理自定义样式的表示控制器。如果您实现了这个方法,那么使用它来创建并返回要用于管理表示过程的自定义表示控制器对象。

If you do not implement this method, or if your implementation of this method returns nil, the system uses a default presentation controller object. The default presentation controller does not add any views or content to the view hierarchy.

如果不实现此方法,或者该方法的实现返回nil,系统将使用默认的表示控制器对象。默认的表示控制器不会向视图层次结构添加任何视图或内容。

Availability Available in iOS 8.0 and later.

iOS 8.0及以后版本的可用性。

For more information watch the WWDC 2014 video:

更多信息请观看WWDC 2014视频:

https://developer.apple.com/videos/wwdc/2014/?include=228

https://developer.apple.com/videos/wwdc/2014/?include=228

There's also a sample code from the WWDC called "LookInside: Presentation Controllers Adaptivity and Custom Animator Objects", which you can download from the WWDC 2014 sample code page.

WWDC也有一个名为“LookInside: Presentation Controllers Adaptivity和Custom Animator Objects”的示例代码,您可以从WWDC 2014示例代码页面下载。

You may need to change the sample code a little bit. The UIPresentationController init method changed to:

您可能需要稍微更改示例代码。UIPresentationController init方法更改为:

initWithPresentedViewController:presented presentingViewController:presenting

Before it was presenting and then presented. Just swap them and it should work.

在它呈现之前,然后呈现。只要交换它们就可以了。

#7


7  

instead of [inView insertSubview:toViewController.view aboveSubview:fromViewController.view]; just add: [inView addSubview:toViewController.view];

而不是(针对我国有关矿山截污库坝insertSubview:toViewController。视图aboveSubview fromViewController.view):;添加:[针对我国有关矿山截污库坝addSubview toViewController.view):;

if (self.presenting) {

    [transitionContext.containerView addSubview:toViewController.view];
    // your code

} else {
    // your code
}

You can see an example here: link and it works on iOS 7 and iOS 8

你可以在这里看到一个例子:link,它可以在ios7和ios8上运行

#8


7  

Here is an Objective C version of Ash's fix.

这是一个目标C版本的Ash修复。

// my attempt at obj-c version of Ash's fix
UIView *theToView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;
[[[UIApplication sharedApplication] keyWindow] addSubview:theToView];
[transitionContext completeTransition:YES]

I had to swap the order and call the [transitionContext completeTransition:] method after adding the view back in to get presenting a new view controller from the dismissal completion block of another view controller to work right.

在将视图添加回后,我必须交换订单并调用[transitionContext completeTransition:]方法,以便从另一个视图控制器的驳回完成块中显示新的视图控制器,使其正常工作。

I don't know that this'll fix it for everyone but it works in my app. Cheers!

我不知道这能不能解决所有人的问题,但在我的应用中,它是有效的。干杯!

#9


5  

I found this worked fine for Obj-C:

我发现这对objective - c很有效:

    [transitionContext completeTransition:YES];
    if(![[UIApplication sharedApplication].keyWindow.subviews containsObject:toViewController.view]) {
        [[UIApplication sharedApplication].keyWindow addSubview:toViewController.view];
    }

Seems to work fine on both ios7 and ios8.

ios7和ios8似乎都很好用。

#10


5  

I found that viewForKey:UITransitionContextToViewKey returns nil on ios8. So if it's nil, I grab the view from the 'to' view controller.

我发现viewForKey:UITransitionContextToViewKey在ios8上返回nil。如果是nil,我从" to "视图控制器中抓取视图。

However, this seems to result in the 'to' view not being moved from the container to the window when completeTransition:YES is called. So if viewForKey:UITransitionContextToViewKey returns nil, I fall over to toVC.view, and keep track of the fact that it returned nil, and after the completion I move it to the container's initial superview (which happens to be the window).

然而,这似乎导致“to”视图在完成转换时不会从容器移动到窗口:YES被调用。所以如果viewForKey:UITransitionContextToViewKey返回nil,我就交给toVC了。查看,并跟踪它返回nil的事实,在完成之后,我将它移动到容器的初始超视图(恰好是窗口)。

So this code works on iOS7 as well as iOS8, and should work on iOS9 too even if they fix it or not.

因此,这段代码在iOS7和iOS8上都有作用,并且应该在iOS9上工作,即使他们修复了。

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
    // Get the 'from' and 'to' views/controllers.
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    BOOL hasViewForKey = [transitionContext respondsToSelector:@selector(viewForKey:)]; // viewForKey is iOS8+.
    UIView *fromView = hasViewForKey ?
        [transitionContext viewForKey:UITransitionContextFromViewKey] :
        fromVC.view;
    UIView *toView = hasViewForKey ?
        [transitionContext viewForKey:UITransitionContextToViewKey] :
        toVC.view;

    // iOS8 has a bug where viewForKey:to is nil: http://*.com/a/24589312/59198
    // The workaround is: A) get the 'toView' from 'toVC'; B) manually add the 'toView' to the container's
    // superview (eg the root window) after the completeTransition call.
    BOOL toViewNilBug = !toView;
    if (!toView) { // Workaround by getting it from the view.
        toView = toVC.view;
    }
    UIView *container = [transitionContext containerView];
    UIView *containerSuper = container.superview; // Used for the iOS8 bug workaround.

    // Perform the transition.
    toView.frame = container.bounds;
    [container insertSubview:toView belowSubview:fromView];
    [UIView animateWithDuration:kDuration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
        fromView.frame = CGRectOffset(container.bounds, 0, CGRectGetHeight(container.bounds));
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:YES];

        if (toViewNilBug) {
            [containerSuper addSubview:toView];
        }
    }];
}

#11


3  

I found that this bug (and many more!) vanishes if you set modalPresentationStyle = UIModalPresentationFullScreen. You of course still get your custom transition animation.

我发现如果你设置modalPresentationStyle = UIModalPresentationFullScreen,这个错误(还有更多的错误!)就会消失。当然,您仍然可以得到定制的转换动画。

#12


2  

After encountering this issue, I was very confused, because I'd written something almost identical not too long ago that worked fine. Came here looking for answers to find fixes that look pretty hacky, and don't seem to understand the root cause... it's actually very easy to fix.

在遇到这个问题后,我很困惑,因为不久前我写了一篇几乎相同的文章,效果很好。来这里寻找解决方案,寻找看上去相当陈腐的解决方案,但似乎不了解根本原因……实际上很容易修复。

Some answers mention changing modalPresentationStyle to .overFullScreen. This is correct, .overCurrentContext would work too. This is expected, and the behaviour Apple documents. But why isn't this working for everyone? Why all the hacky code, and combinations of this with something else, and crazy stuff that you shouldn't be doing?

有些回答提到将modalPresentationStyle改为. overfullscreen。这是正确的,. overcurrentcontext也可以。这是意料之中的,也是苹果公司所记录的行为。但为什么这不是对所有人都有效呢?为什么所有的代码,以及这些代码与其他东西的组合,以及你不应该做的疯狂的事情?

Turns out, you need to set the presentation style BEFORE THE VIEW LOADS. Not after. Do it in init, or do it from the previous controller, or however you'd like - as long as it is before the view loads.

结果是,您需要在视图加载之前设置表示样式。不后。在init中执行,或者从以前的控制器中执行,或者按照您希望的方式执行——只要在视图加载之前执行。

#13


1  

Using the new UIModalPresentationOverCurrentContext fixed it for me. My original transition on iOS 7 was just to have a blurred background of the view underneath the modal.

使用新的UIModalPresentationOverCurrentContext为我修复了它。我在ios7上最初的过渡就是在模态下设置模糊的背景。

#14


1  

I got stuck on this issue too. I was looking to create a custom transition with a semi-transparent background where I could still see the view controller I was coming from but I only got a black background. I found Mark Aron's answer in this thread helped me but it is written in Objective C so here is a Swift 3 version of that answer which I have tested for iOS 9 and iOS 10:

我也被这个问题困住了。我想创建一个带有半透明背景的自定义转换,在那里我仍然可以看到我来自的视图控制器,但是我只有一个黑色背景。我发现Mark Aron的答案在这个线程中帮助了我,但它写的是Objective - C所以这是一个Swift 3版本的答案我已经测试了ios9和ios10:

  1. Create a subclass of UIPresentationController. Override the shouldRemovePresentersView to false as follows:

    创建UIPresentationController的子类。将shouldremovepressview重写为false,如下所示:

    class ModalPresentationController: UIPresentationController {
    
    override var shouldRemovePresentersView: Bool {
    return false
    }
    
    override func containerViewWillLayoutSubviews() {
    presentedView?.frame = frameOfPresentedViewInContainerView
    }
    }
    
  2. In the place you are instantiating the new view controller and setting its transition delegate, indicate that you want it to show a custom modal presentation style as follows:

    在实例化新视图控制器并设置其转换委托的地方,指示它显示自定义模态表示样式如下:

    let newVC = mainStoryboard.instantiateViewController(withIdentifier: "newVC") as! NewViewController 
    
    newVC.transitioningDelegate = self
    
    newVC.modalPresentationStyle = UIModalPresentationStyle.custom
    
    newVC.modalPresentationCapturesStatusBarAppearance = true //optional
    
    present(newVC, animated: true, completion: nil)
    
  3. Now override the presentationController method of your UIViewControllerTransitioningDelegate and return your custom UIPresentationController. I had mine as an extension to my current class:

    现在重写UIViewControllerTransitioningDelegate的presentationController方法并返回自定义的UIPresentationController。我把我的课程扩展到现在的课程:

    extension CurrentViewController: UIViewControllerTransitioningDelegate {
    
    //this is where you implement animationController(forPresented) and animationController(forDismissed) methods
    
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
    
    return ModalPresentationController(presentedViewController: presented, presenting: source)
    
    }
    }
    

One other thing to note is you should not try and reference your fromView in your presentAnimator class. This will be nil and you will get an error at runtime. Other than that if you implement things like things you will get your custom transition with its animation and a semi-transparent background if you make one.

另外需要注意的一点是,不应该尝试在presentAnimator类中引用fromView。这将是nil,你将在运行时得到一个错误。除此之外,如果你实现了像这样的东西,你会得到你的自定义过渡动画和半透明背景,如果你做一个。

#15


-2  

adds a view controller as a child of another view controller.

添加一个视图控制器作为另一个视图控制器的子。

[self addChildViewController:childViewController];                 

check and let me know.

检查一下,让我知道。

#1


94  

I was having the same problem here – looks like a bug in iOS 8. I've filed a radar.

我在这里遇到了同样的问题——看起来像是iOS 8中的一个bug。我提出了雷达。

I used Reveal to inspect the view hierarchy after the screen goes black. The key UIWindow is completely empty – no view hierarchy at all!

在屏幕变黑后,我使用了显示来检查视图层次结构。关键的UIWindow是完全空的——完全没有视图层次结构!

“从视图控制器”在使用uiviewcontrollercontexttransfer时消失

I played around a bit and it looks like there is an easy workaround, for simple cases. You can just re-add the toViewController's view as a subview of the key window's:

我尝试了一下,看起来有一个简单的解决方案。你可以重新添加toViewController的视图作为键窗口的子视图:

transitionContext.completeTransition(true)
UIApplication.sharedApplication().keyWindow!.addSubview(toViewController.view)

I've checked and the key window's rootViewController is still correctly set, so that's fine. I'm not sure what would happen if you presented your controller from within an already presented modal controller, so for more complex cases, you'll have to experiment around.

我已经检查过了,关键窗口的rootViewController仍然正确设置,所以没关系。我不确定如果你在一个已经展示过的模态控制器中展示你的控制器会发生什么,所以对于更复杂的情况,你必须进行实验。

#2


67  

I feel like the reasoning behind this should be explained better.

我觉得这背后的原因应该得到更好的解释。

The view disappears because you take out the presenting view controller's view out of its original location (view hierarchy), put it inside the containerView that your animator provides but never returns it back after the animation has finished. So that view controller's view is removed with its superview (containerView) from the window completely.

视图之所以消失,是因为您将呈现视图控制器的视图从其原始位置(视图层次结构)中取出,并将其放入动画师提供的containerView中,但动画完成后永不返回。这样视图控制器的视图就会被它的超视图(containerView)从窗口中删除。

In iOS 7 the system always returned view controllers' views that are involved in the presentation (presenting and presented) to their original places after the transition has finished animating automatically. That no longer happens for some presentation styles in iOS 8.

在ios7系统中,在转换完成自动动画后,系统总是将视图控制器的视图返回到它们的原始位置(呈现和呈现)。在iOS 8中,这种情况不再发生。

The rule is very simple: the animator should only manipulate the presenting view controller's view if that view controller's view is going to be hidden (removed from the view hierarchy) completely by the end of transition. In other words it means that after the initial presentation animation finishes only the presented view controller's view will be visible and not the presenting view controller's view. For example if you set presented view controller's view's opacity to 50% and use UIModalPresentationFullScreen you will not be able to see presenting view controller's view underneath the presented but if you use UIModalPresentationOverFullscreen - you will (UIPresentationController's shouldRemovePresentersView method is responsible for specifying that).

规则非常简单:如果视图控制器的视图在转换结束时完全隐藏(从视图层次结构中删除),动画器只应该操作呈现视图控制器的视图。换句话说,它意味着在初始表示动画完成后,只有显示视图控制器的视图是可见的,而不是显示视图控制器的视图。例如,如果你将显示视图控制器的不透明度设置为50%并使用UIModalPresentationFullScreen你将不能看到显示视图控制器的视图在显示视图下面,但是如果你使用UIModalPresentationOverFullscreen你会(UIPresentationController的shouldremovepressview方法负责指定)。

Why not allow the animator manipulate the presenting view controller's view at all times? First of all, if the presenting view controller's view is going to stay visible after the animation finishes during the whole presentation life cycle there is no need to animate it at all — it just stays where it is. Second, if the ownership for that view controller is transferred to the presentation controller, the presentation controller will most likely not know how to layout that view controller's view when needed for example when the orientation changes, but the original owner of the presenting view controller does.

为什么不让动画师一直操作呈现视图控制器的视图呢?首先,如果表示视图控制器的视图在整个表示生命周期中动画完成后仍然可见,那么就根本不需要对它进行动画处理——它只是停留在原来的位置。第二,如果该视图控制器的所有权被转移到表示控制器,表示控制器很可能不知道在需要时如何布局该视图控制器的视图,当方向发生变化时,但是present视图控制器的原始所有者会这样做。

In iOS 8 viewForKey: method was introduced to get views that the animator manipulates. First, it helps to follow the rule described above by returning nil whenever the animator should not touch the view. Second, it may return a different view for the animator to animate. Imagine that you are implementing a presentation similar to form sheet. In this case you would want to add some shadow or decoration around the presented view controller's view. The animator will animate that decoration instead and the presented view controller's view will be a child of the decoration.

在ios8 viewForKey:中引入了获取动画师操作的视图的方法。首先,当动画师不应该触碰视图时,返回nil,这有助于遵循上面描述的规则。其次,它可能会返回一个不同的视图给动画师。假设您正在实现一个类似于表单表的表示。在这种情况下,您可能希望在呈现的视图控制器的视图周围添加一些阴影或修饰。动画师会将那个装饰动画化,而呈现的视图控制器的视图将是装饰的子元素。

viewControllerForKey: doesn't go away, it can still be used if a direct access to view controllers is needed but the animator should not make any assumptions about the views it needs to animate.

viewControllerForKey:不会消失,如果需要直接访问视图控制器,仍然可以使用它,但是动画师不应该对要动画的视图做任何假设。

There are several things you can do to correctly fix an issue with a disappearing presenting view controller's view when you explicitly place it inside the animator's container view:

当您显式地将视图放入动画师的容器视图中时,您可以通过以下几项来正确地修复正在消失的显示视图控制器视图的问题:

  1. If do not need to animate the presenting view controller's view, use viewForKey: to get views to animate instead of reaching out to view controller's views directly. viewForKey: may return nil or even completely different views.

    如果不需要动画显示视图控制器的视图,请使用viewForKey:获取视图动画,而不是直接访问视图控制器的视图。viewForKey:可能返回nil,甚至完全不同的视图。

  2. If you want to animate the presenting view controllers's view you should consider using UIModalPresentationFullScreen style or continue using UIModalPresentationCustom and implement your own subclass of UIPresentationController with shouldRemovePresentersView returning YES. In fact, the implementation of this method is the main difference between internal presentation controllers defined by UIModalPresentationFullScreen and UIModalPresentationCustom styles apart from the fact that the latter allows you to use custom presentation controllers.

    如果你想要激活呈现视图控制器的视图你应该考虑使用UIModalPresentationFullScreen样式或者继续使用UIModalPresentationCustom实现你自己的UIPresentationController的子类用shouldremovepresentsview返回YES。实际上,这个方法的实现是UIModalPresentationFullScreen定义的内部表示控制器和UIModalPresentationCustom风格之间的主要区别,除了后者允许您使用自定义表示控制器之外。

  3. In all other rare cases you will have to return the presenting view controller's view to its original location as other answers suggested.

    在所有其他罕见的情况下,您将不得不像其他答案所建议的那样将呈现视图控制器的视图返回到其原始位置。

#3


66  

In iOS 8, you must manipulate the views returned by viewForKey: instead of the .view property of the view controllers returned by viewControllerForKey:. This isn't particularly clear from the beta documentation, but if you look into the source for UIViewControllerTransitioning.h you'll see this comment above viewControllerForKey::

在ios8中,必须操作viewForKey返回的视图:而不是viewControllerForKey返回的视图控制器的.view属性:。这在beta文档中并不是特别清楚,但是如果您查看uiviewcontrollertransition的源代码的话。h你会看到以上viewControllerForKey:

// Currently only two keys are defined by the
// system - UITransitionContextToViewControllerKey, and
// UITransitionContextFromViewControllerKey.
// Animators should not directly manipulate a view controller's views and should
// use viewForKey: to get views instead.
- (UIViewController *)viewControllerForKey:(NSString *)key;

So instead of adjusting frames etc of toViewController.view, use the return value of [transitionContext viewForKey:UITransitionContextToViewKey].

不是调整toViewController的帧等等。查看,使用[transitionContext viewForKey:UITransitionContextToViewKey]的返回值。

If your app needs to support iOS7 and/or Xcode 5, then you can use a simple category method on UIViewController like the following:

如果您的应用程序需要支持iOS7和/或Xcode 5,那么您可以在UIViewController上使用一个简单的类别方法如下:

- (UIView *)viewForTransitionContext:(id<UIViewControllerContextTransitioning>)transitionContext
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
    if ([transitionContext respondsToSelector:@selector(viewForKey:)]) {
        NSString *key = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey] == self ? UITransitionContextFromViewKey : UITransitionContextToViewKey;
        return [transitionContext viewForKey:key];
    } else {
        return self.view;
    }
#else
    return self.view;
#endif
}

Then, get your toViewController and fromViewController as usual, but get the views using [toViewController viewForTransitionContext:transitionContext].

然后,像往常一样获取toViewController和fromViewController,但是使用[toViewController viewForTransitionContext:transitionContext]获取视图。

Edit: There appears to be a bug, where the presenting view controller's view is nil when returned from viewForKey, which prevents you from making modal transitions that animate the presenting view at all (such as sliding off, or flip-horizontal). I filed a bug for iOS8 at rdar://17961976 (http://openradar.appspot.com/radar?id=5210815787433984). Also see the sample project at http://github.com/bcherry/TransitionBug

编辑:似乎有一个bug,当从viewForKey返回时,呈现视图控制器的视图为nil,这阻止您进行模式转换,从而使呈现视图完全活跃(例如滑动或水平切换)。我在rdar://17961976 (http://openradar.appspot.com/radar?id=5210815787433984)为iOS8提交了一个bug。还可以在http://github.com/bcherry/TransitionBug上看到示例项目

Edit 2: Thanks to graveley for the suggestion, using UIModalPresentationFullScreen fixes the issue. Perhaps this is not a bug. Apple may intend that UIModalPresentationCustom only modifies the view of the incoming modal. If you want to modify the outgoing view, you need to guarantee full screen presentation of the new view? In any case, you should use viewForKey and UIModalPresentationFullScreen.

编辑2:感谢graveley的建议,使用UIModalPresentationFullScreen解决这个问题。也许这不是一个错误。苹果可能打算UIModalPresentationCustom只修改传入模式的视图。如果要修改传出视图,需要保证新视图的全屏显示?无论如何,您应该使用viewForKey和UIModalPresentationFullScreen。

#4


22  

Not setting modalPresentationStyle to UIModalPresentationCustom fixed the issue for me.

不设置modalPresentationStyle到UIModalPresentationCustom为我解决这个问题。

In other words, leaving at the default of UIModalPresentationFullScreen instead of specifying UIModalPresentationCustom fixed the disappearing view issue. Note the UIViewControllerTransitioningDelegate protocol still seems to be followed even when leaving this at the default. If i recall correctly, once upon a time UIModalPresentationCustom was a requirement.

换句话说,在UIModalPresentationFullScreen的默认状态下离开,而不是指定UIModalPresentationCustom修复消失的视图问题。注意,UIViewControllerTransitioningDelegate协议似乎仍然遵循,即使在默认设置下。如果我没记错的话,曾几何时UIModalPresentationCustom是一个需求。

Works so far, have only tried this for non-interactive animations.

到目前为止,作品只尝试过非交互式动画。

#5


12  

I've found this extremely useful answer in a related thread by Lefteris: https://*.com/a/27165723/3709173

我在一个相关的线程中找到了这个非常有用的答案:https://*.com/a/27165723/3709173。

To sum it up:

总结一下:

  1. set modalPresentationStyle to .Custom
  2. 设置modalPresentationStyle .Custom
  3. subclass UIPresentationController, override shouldRemovePresentersView (with NO)
  4. UIPresentationController的子类,覆盖shouldremovepressview(没有)
  5. override presentationControllerForPresentedViewController in your TransitionDelegate class and return your custom UIPresentationController
  6. 在TransitionDelegate类中重写presentationControllerForPresentedViewController并返回自定义的UIPresentationController。

+1 in your custom transition, don't add toView when the dismissal animation is happening.

+1在你的自定义转换中,当解雇动画发生时,不要添加toView。

Demonstrated here:

证明:

https://www.dropbox.com/s/7rpkyamv9k9j18v/CustomModalTransition.zip?dl=0 without any hacks! it's like magic! :)

https://www.dropbox.com/s/7rpkyamv9k9j18v/CustomModalTransition.zip?dl = 0,没有任何黑客!它就像魔法!:)

#6


8  

In iOS 8, you need create a UIPresentationController and implement the method below, in the UIViewControllerTransitioningDelegate.

在ios8中,需要创建一个UIPresentationController并在UIViewControllerTransitioningDelegate中实现下面的方法。

- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source;

Asks your delegate for the custom presentation controller to use for managing the view hierarchy when presenting a view controller.

请委托自定义表示控制器在显示视图控制器时用于管理视图层次结构。

Return Value:

返回值:

The custom presentation controller for managing the modal presentation.

用于管理模态表示的自定义表示控制器。

Discussion:

讨论:

When you present a view controller using the UIModalPresentationCustom presentation style, the system calls this method and asks for the presentation controller that manages your custom style. If you implement this method, use it to create and return the custom presentation controller object that you want to use to manage the presentation process.

当您使用UIModalPresentationCustom表示样式呈现一个视图控制器时,系统会调用这个方法并请求管理自定义样式的表示控制器。如果您实现了这个方法,那么使用它来创建并返回要用于管理表示过程的自定义表示控制器对象。

If you do not implement this method, or if your implementation of this method returns nil, the system uses a default presentation controller object. The default presentation controller does not add any views or content to the view hierarchy.

如果不实现此方法,或者该方法的实现返回nil,系统将使用默认的表示控制器对象。默认的表示控制器不会向视图层次结构添加任何视图或内容。

Availability Available in iOS 8.0 and later.

iOS 8.0及以后版本的可用性。

For more information watch the WWDC 2014 video:

更多信息请观看WWDC 2014视频:

https://developer.apple.com/videos/wwdc/2014/?include=228

https://developer.apple.com/videos/wwdc/2014/?include=228

There's also a sample code from the WWDC called "LookInside: Presentation Controllers Adaptivity and Custom Animator Objects", which you can download from the WWDC 2014 sample code page.

WWDC也有一个名为“LookInside: Presentation Controllers Adaptivity和Custom Animator Objects”的示例代码,您可以从WWDC 2014示例代码页面下载。

You may need to change the sample code a little bit. The UIPresentationController init method changed to:

您可能需要稍微更改示例代码。UIPresentationController init方法更改为:

initWithPresentedViewController:presented presentingViewController:presenting

Before it was presenting and then presented. Just swap them and it should work.

在它呈现之前,然后呈现。只要交换它们就可以了。

#7


7  

instead of [inView insertSubview:toViewController.view aboveSubview:fromViewController.view]; just add: [inView addSubview:toViewController.view];

而不是(针对我国有关矿山截污库坝insertSubview:toViewController。视图aboveSubview fromViewController.view):;添加:[针对我国有关矿山截污库坝addSubview toViewController.view):;

if (self.presenting) {

    [transitionContext.containerView addSubview:toViewController.view];
    // your code

} else {
    // your code
}

You can see an example here: link and it works on iOS 7 and iOS 8

你可以在这里看到一个例子:link,它可以在ios7和ios8上运行

#8


7  

Here is an Objective C version of Ash's fix.

这是一个目标C版本的Ash修复。

// my attempt at obj-c version of Ash's fix
UIView *theToView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;
[[[UIApplication sharedApplication] keyWindow] addSubview:theToView];
[transitionContext completeTransition:YES]

I had to swap the order and call the [transitionContext completeTransition:] method after adding the view back in to get presenting a new view controller from the dismissal completion block of another view controller to work right.

在将视图添加回后,我必须交换订单并调用[transitionContext completeTransition:]方法,以便从另一个视图控制器的驳回完成块中显示新的视图控制器,使其正常工作。

I don't know that this'll fix it for everyone but it works in my app. Cheers!

我不知道这能不能解决所有人的问题,但在我的应用中,它是有效的。干杯!

#9


5  

I found this worked fine for Obj-C:

我发现这对objective - c很有效:

    [transitionContext completeTransition:YES];
    if(![[UIApplication sharedApplication].keyWindow.subviews containsObject:toViewController.view]) {
        [[UIApplication sharedApplication].keyWindow addSubview:toViewController.view];
    }

Seems to work fine on both ios7 and ios8.

ios7和ios8似乎都很好用。

#10


5  

I found that viewForKey:UITransitionContextToViewKey returns nil on ios8. So if it's nil, I grab the view from the 'to' view controller.

我发现viewForKey:UITransitionContextToViewKey在ios8上返回nil。如果是nil,我从" to "视图控制器中抓取视图。

However, this seems to result in the 'to' view not being moved from the container to the window when completeTransition:YES is called. So if viewForKey:UITransitionContextToViewKey returns nil, I fall over to toVC.view, and keep track of the fact that it returned nil, and after the completion I move it to the container's initial superview (which happens to be the window).

然而,这似乎导致“to”视图在完成转换时不会从容器移动到窗口:YES被调用。所以如果viewForKey:UITransitionContextToViewKey返回nil,我就交给toVC了。查看,并跟踪它返回nil的事实,在完成之后,我将它移动到容器的初始超视图(恰好是窗口)。

So this code works on iOS7 as well as iOS8, and should work on iOS9 too even if they fix it or not.

因此,这段代码在iOS7和iOS8上都有作用,并且应该在iOS9上工作,即使他们修复了。

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
    // Get the 'from' and 'to' views/controllers.
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    BOOL hasViewForKey = [transitionContext respondsToSelector:@selector(viewForKey:)]; // viewForKey is iOS8+.
    UIView *fromView = hasViewForKey ?
        [transitionContext viewForKey:UITransitionContextFromViewKey] :
        fromVC.view;
    UIView *toView = hasViewForKey ?
        [transitionContext viewForKey:UITransitionContextToViewKey] :
        toVC.view;

    // iOS8 has a bug where viewForKey:to is nil: http://*.com/a/24589312/59198
    // The workaround is: A) get the 'toView' from 'toVC'; B) manually add the 'toView' to the container's
    // superview (eg the root window) after the completeTransition call.
    BOOL toViewNilBug = !toView;
    if (!toView) { // Workaround by getting it from the view.
        toView = toVC.view;
    }
    UIView *container = [transitionContext containerView];
    UIView *containerSuper = container.superview; // Used for the iOS8 bug workaround.

    // Perform the transition.
    toView.frame = container.bounds;
    [container insertSubview:toView belowSubview:fromView];
    [UIView animateWithDuration:kDuration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
        fromView.frame = CGRectOffset(container.bounds, 0, CGRectGetHeight(container.bounds));
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:YES];

        if (toViewNilBug) {
            [containerSuper addSubview:toView];
        }
    }];
}

#11


3  

I found that this bug (and many more!) vanishes if you set modalPresentationStyle = UIModalPresentationFullScreen. You of course still get your custom transition animation.

我发现如果你设置modalPresentationStyle = UIModalPresentationFullScreen,这个错误(还有更多的错误!)就会消失。当然,您仍然可以得到定制的转换动画。

#12


2  

After encountering this issue, I was very confused, because I'd written something almost identical not too long ago that worked fine. Came here looking for answers to find fixes that look pretty hacky, and don't seem to understand the root cause... it's actually very easy to fix.

在遇到这个问题后,我很困惑,因为不久前我写了一篇几乎相同的文章,效果很好。来这里寻找解决方案,寻找看上去相当陈腐的解决方案,但似乎不了解根本原因……实际上很容易修复。

Some answers mention changing modalPresentationStyle to .overFullScreen. This is correct, .overCurrentContext would work too. This is expected, and the behaviour Apple documents. But why isn't this working for everyone? Why all the hacky code, and combinations of this with something else, and crazy stuff that you shouldn't be doing?

有些回答提到将modalPresentationStyle改为. overfullscreen。这是正确的,. overcurrentcontext也可以。这是意料之中的,也是苹果公司所记录的行为。但为什么这不是对所有人都有效呢?为什么所有的代码,以及这些代码与其他东西的组合,以及你不应该做的疯狂的事情?

Turns out, you need to set the presentation style BEFORE THE VIEW LOADS. Not after. Do it in init, or do it from the previous controller, or however you'd like - as long as it is before the view loads.

结果是,您需要在视图加载之前设置表示样式。不后。在init中执行,或者从以前的控制器中执行,或者按照您希望的方式执行——只要在视图加载之前执行。

#13


1  

Using the new UIModalPresentationOverCurrentContext fixed it for me. My original transition on iOS 7 was just to have a blurred background of the view underneath the modal.

使用新的UIModalPresentationOverCurrentContext为我修复了它。我在ios7上最初的过渡就是在模态下设置模糊的背景。

#14


1  

I got stuck on this issue too. I was looking to create a custom transition with a semi-transparent background where I could still see the view controller I was coming from but I only got a black background. I found Mark Aron's answer in this thread helped me but it is written in Objective C so here is a Swift 3 version of that answer which I have tested for iOS 9 and iOS 10:

我也被这个问题困住了。我想创建一个带有半透明背景的自定义转换,在那里我仍然可以看到我来自的视图控制器,但是我只有一个黑色背景。我发现Mark Aron的答案在这个线程中帮助了我,但它写的是Objective - C所以这是一个Swift 3版本的答案我已经测试了ios9和ios10:

  1. Create a subclass of UIPresentationController. Override the shouldRemovePresentersView to false as follows:

    创建UIPresentationController的子类。将shouldremovepressview重写为false,如下所示:

    class ModalPresentationController: UIPresentationController {
    
    override var shouldRemovePresentersView: Bool {
    return false
    }
    
    override func containerViewWillLayoutSubviews() {
    presentedView?.frame = frameOfPresentedViewInContainerView
    }
    }
    
  2. In the place you are instantiating the new view controller and setting its transition delegate, indicate that you want it to show a custom modal presentation style as follows:

    在实例化新视图控制器并设置其转换委托的地方,指示它显示自定义模态表示样式如下:

    let newVC = mainStoryboard.instantiateViewController(withIdentifier: "newVC") as! NewViewController 
    
    newVC.transitioningDelegate = self
    
    newVC.modalPresentationStyle = UIModalPresentationStyle.custom
    
    newVC.modalPresentationCapturesStatusBarAppearance = true //optional
    
    present(newVC, animated: true, completion: nil)
    
  3. Now override the presentationController method of your UIViewControllerTransitioningDelegate and return your custom UIPresentationController. I had mine as an extension to my current class:

    现在重写UIViewControllerTransitioningDelegate的presentationController方法并返回自定义的UIPresentationController。我把我的课程扩展到现在的课程:

    extension CurrentViewController: UIViewControllerTransitioningDelegate {
    
    //this is where you implement animationController(forPresented) and animationController(forDismissed) methods
    
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
    
    return ModalPresentationController(presentedViewController: presented, presenting: source)
    
    }
    }
    

One other thing to note is you should not try and reference your fromView in your presentAnimator class. This will be nil and you will get an error at runtime. Other than that if you implement things like things you will get your custom transition with its animation and a semi-transparent background if you make one.

另外需要注意的一点是,不应该尝试在presentAnimator类中引用fromView。这将是nil,你将在运行时得到一个错误。除此之外,如果你实现了像这样的东西,你会得到你的自定义过渡动画和半透明背景,如果你做一个。

#15


-2  

adds a view controller as a child of another view controller.

添加一个视图控制器作为另一个视图控制器的子。

[self addChildViewController:childViewController];                 

check and let me know.

检查一下,让我知道。