viewDidAppear调用了一个在iOS8中被解雇的viewcontroller

时间:2014-10-20 14:30:11

标签: ios objective-c iphone uiviewcontroller ios8

让我们假设ParentViewcontroller为P,FirstViewController为V1,SecondViewController为V2。

我从P中呈现V1,然后从V1呈现V2。现在我想直接去P.为此我正在使用

[self.presentingViewController.presentingViewController dismissViewControllerAnimated:NO completion:nil];

这在iOS7中运行良好。但是在iOS8中我做这个时遇到了一个问题(不知道是不是问题)。这就是调用V1的viewDidAppear方法,并且它的视图在屏幕上出现故障只需几秒钟。

这是iOS8功能还是bug?有没有其他方法可以做到这一点?

ViewControllers呈现代码。

从P开始,其中P是推送的视图控制器,

ViewController1 *v1 = [[ViewController1 alloc] init];      
[self presentViewController:v1 animated:NO completion:nil];

从V1,

ViewController2 *v2 = [[ViewController2 alloc] init];
[self presentViewController:v2 animated:NO completion:nil];

3 个答案:

答案 0 :(得分:0)

你可以使用你的V1嵌入NavigationController(NV)吗?这样,你可以推动你的V2。 然后您可以弹出到V1或将NV关闭到P。

答案 1 :(得分:0)

通过修补问题,花了很多时间进行研究。

我做的是,在解除ViewController(V2)之前,我捕获了一个ParentViewcontroller(P)的屏幕截图并将其添加到应用程序窗口。然后在ViewController(V2)被解雇后从窗口中删除图像。

CGRect deviceRect = [[UIScreen mainScreen] bounds];

UIGraphicsBeginImageContextWithOptions(deviceRect.size, NO, [UIScreen mainScreen].scale);
CGContextRef contextRef = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(contextRef, -deviceRect.origin.x, -deviceRect.origin.y);
[[self.presentingViewController.presentingViewController.view layer] renderInContext:contextRef];
UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

UIImageView *windowImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, deviceRect.size.width, deviceRect.size.height)];
[windowImageView setImage:capturedImage];
[[[UIApplication sharedApplication] keyWindow] addSubview:windowImageView];

[self.presentingViewController.presentingViewController dismissViewControllerAnimated:NO completion:^
{
      [windowImageView removeFromSuperview];
}];

答案 2 :(得分:0)

' viewWill / DidAppear'当你解散时,调用V1是合乎逻辑的,因为技术上在顶层viewController(V2)的模态解雇中暴露了V1,如果只有足够长的时间,UIKit就会被赋予去除下一个底层viewController(例如V1)的任务。

我的猜测是iOS8中的V1视觉故障不是一个错误,更多的是关于iOS如何处理在iOS8中解雇模态内部模式。由于不存在针对该情况的文档,因此其实际行为可以合法地从iOS更改为iOS。

我认为一种方法可以做你想做的事情,保持你对旧iOS的向后兼容性,并使用具有记录行为的API,将使用如下的代码(也许作为一个类别在UIViewController上)。动画V1,然后简单地删除它(下面的#2)。 V2可能会使用标准的iOS' presentViewController'在V1内部动画,但你也可以使用方法#1。

需要注意的是,由于您将V1.view作为子视图添加到P而不是通过UIViewController模式系统,因此您将失去V1中的自动viewWill / DidAppear调用。所以你需要手动调用它们。在这个例子中,它们是在“动画”中调用的。类别方法。

这不是我实际使用的代码,但我过去做过类似的事情。所以要小心一点,如果发现错误请发表评论....假设ARC:

希望这有帮助。

    //1. animate V1 up (executed from P)
    ViewController  * V1 = [[ViewController1 alloc] init];
    //place V1 view below bottom of P
    V1.view.frame = CGRectMake(0, UI_phone_height, UI_phone_width, UI_phone_height);
    [self.view addSubview: V1.view]; //'self' is P
    [V1 customAnimateUpCategory];

    // >> method #1 in a UIViewController category
    - (void) customAnimateUpCategory {

            //...optional
            [self viewWillAppear];

            [UIView animateWithDuration:0.4
                     animations:^ {
                         //animate V1.view up
                         self.view.frame = CGRectMake(0, 0, UI_phone_width, UI_phone_height);
                     }
                     completion:^ (BOOL finished) {
                         if (finished) {
                             //...optional
                             [self viewDidAppear];
                         }
                     }
            ];
    }


    //2. make V1/V2 disappear without animation (executed from V2)
    //'V1' is weakly held in V2 as an IVAR
    [self.V1 removeViewCategory]

    // >> method #2 in a UIViewController category
    - (void) removeViewCategory {
            [self.view removeFromSuperview];//should remove and release V1/V2 glitch free!!
    }