在“模态”呈现的视图控制器出现后,现在呈现的视图控制器下的视图将被删除;这可以节省内存并简化渲染。但是,在您的情况下,您最终也会看到“模态”呈现视图后面的窗口。
下一步自然且看似合乎逻辑的做法是简单地获取一个视图控制器的视图并将其塞入另一个视图控制器中。但是,正如您所发现的,这是有问题的。新插入的视图被视图层次结构安全地保留,它是安全的,但是新的视图控制器就没有那么幸运了,它很快就被释放了。所以当这个新视图试图联系它的控制器时,你会得到一个EXC_BAD_ACCESS
并且崩溃。正如您所发现的,一种解决方法是简单地让原始视图控制器保持对新视图控制器的强引用。这可以工作......很糟糕。您仍然很有可能获得UIViewControllerHierarchyInconsistencyException
.
当然,如果您只是想添加在 IB 中创建的小视图,则不需要将视图控制器用作“ ”,并且有许多从文件File's Owner
创建视图实例的示例。xib
这里更有趣的问题是,“苹果将/如何做到这一点?” Apple 一直说视图控制器是封装工作单元的正确控制器。例如,他们的TWTweetComposeViewController
,你呈现它,它似乎是浮动的。如何?
我想到的第一个实现这一点的方法是有一个不清楚的背景。也就是说,在呈现的视图控制器出现之前创建屏幕图像,并将其设置为背景,然后再移除呈现的视图。所以例如(解释如下):
QuickSheetViewController.xib
QuickSheetViewController.h
#import <UIKit/UIKit.h>
@interface QuickSheetViewController : UIViewController
- (IBAction)dismissButtonPressed:(id)sender;
@end
QuickSheetViewController.m
#import "QuickSheetViewController.h"
#import <QuartzCore/QuartzCore.h>
@implementation QuickSheetViewController {
UIImage *_backgroundImage;
}
-(void)renderAndSaveBackgroundImageFromVC:(UIViewController *)vc{
UIGraphicsBeginImageContext(vc.view.bounds.size);
[vc.view.layer renderInContext:UIGraphicsGetCurrentContext()];
_backgroundImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// save an image of the current view, and set our background to clear so we can see the slide-in.
[self renderAndSaveBackgroundImageFromVC:self.presentingViewController];
self.view.backgroundColor = [UIColor clearColor];
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
// Time to use our saved background image.
self.view.backgroundColor = [UIColor colorWithPatternImage:_backgroundImage];
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
// Set our background to clear so we can see the slide-out.
self.view.backgroundColor = [UIColor clearColor];
}
- (IBAction)dismissButtonPressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
@end
这个例子的大部分取决于renderAndSaveBackgroundImageFromVC:
方法。在其中,我们创建了一个图形上下文,将我们即将覆盖的视图渲染到其中,然后创建一个UIImage
以供稍后(in viewDidAppear
)用作背景。
现在只需像这样使用它:
QuickSheetViewController *newVC = [[QuickSheetViewController alloc] initWithNibName:nil bundle:nil];
[self presentViewController:newVC animated:YES completion:nil];
您将看到背景足够长的时间以使动画发生,然后我们使用保存的图像来隐藏当前视图的删除。