簡體   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