繁体   English   中英

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

[英]Adding another view controller's view as subview

我试图获得弹出效果,并想在另一个视图控制器中设计弹出视图,以便我可以使用xib来做到这一点。

当我使用presentViewController或pushViewController并将背景设置为透明时,我最终看到的是窗口的背景色。

我尝试使用此代码将子视图添加到导航控制器的视图中,以便可以使信息视图以透明背景覆盖整个屏幕。 我也有选项卡栏来掩盖。

InfoVC *vc = [[InfoVC alloc] initWithNibName:@"InfoVC" bundle:nil];
[self.navigationController.view addSubview:vc.view];

我的问题出在我试图关闭它的InfoVC内时,该应用程序将崩溃并显示一些EXC_BAD_ACCESS消息:

[self.view removeFromSuperview];

编辑:

我找到了一种防止崩溃的方法,但是将InfoVC设置为MainVC中的一个属性。 我认为崩溃的原因是当我在InfoVC内部的动作中调用“ self.view”时,它不知道self是MainVC内部的InfoVC。

InfoVC *vc = [[InfoVC alloc] initWithNibName:@"InfoVC" bundle:nil];
[self.navigationController.view addSubview:vc.view];

不不不不。 永远不要那样做。

如果没有内置执行此操作的内置功能(如UISplitViewController的操作),则必须遍历此操作才能将视图控制器的视图放入另一个视图控制器的视图中(或在以后将其删除)。导航控制器管理在其中推送和弹出的视图控制器的视图的方式)。

阅读客户容器控制器上的内容。 我的书中的示例之一在这里:

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/ch19p556containerController/p476containerController/ViewController.m

您不应该使用以下内容从其超级视图中删除该视图吗?

[vc.view removeFromSuperview];

您永远无法让UIView删除其子视图,子视图本身必须将其从其父视图中删除。 您可以轻松地循环浏览子视图,并像这样将其删除

for (UIView *view in vc.view.subviews) {
  [view removeFromSuperview];
}

参考文档: http : //developer.apple.com/library/ios/#documentation/uikit/reference/uiview_class/uiview/uiview.html

在“模态化”呈现的视图控制器出现之后,现在呈现的视图控制器下的视图将被删除; 这样可以节省内存并简化渲染。 但是,就您的情况而言,您最终还会看到“模态”显示视图后面的窗口。

看起来自然而合理的下一步就是简单地将一个视图控制器的视图添加到另一个视图控制器中。 但是,正如您所发现的,这是有问题的。 在新插入的视图安全地保留在视图层次结构中的情况下,它是安全的,但是新的视图控制器并不是那么幸运,它很快就被释放了。 因此,当此新视图尝试联系其控制器时,您将获得EXC_BAD_ACCESS并崩溃。 再次发现,一种解决方法是仅使原始视图控制器对新视图控制器保持强大的引用。 这可能会很糟糕。 您仍然有机会获得UIViewControllerHierarchyInconsistencyException

当然,如果您只是想添加在IB中创建的小视图,则不需要将视图控制器用作“ File's Owner ”,并且有许多示例可以从xib文件创建视图实例。

这里更有趣的问题是:“苹果会/会如何做?” 苹果公司一贯认为,视图控制器是封装工作单元的正确控制器。 例如,您展示了它们的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稍后(在viewDidAppear )用作背景。

现在只需像这样使用它:

QuickSheetViewController *newVC = [[QuickSheetViewController alloc] initWithNibName:nil bundle:nil];
[self presentViewController:newVC animated:YES completion:nil];

您将通过背景看到足够长的时间以使动画发生,然后我们使用保存的图像来隐藏呈现视图的移除。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM