Sharing a UIView across multiple UIViewControllers

2019-08-03 21:31发布

问题:

Is there way to share a UIView between a parent and child UIViewController without any noticeable visual glitches when it's added to the child's view as a subview?

I have a UIViewController and its corresponding UIView, considered as a 'masthead', that will be shared between a parent and child UIViewController. (image something like a stock ticker that will be present somewhere on the screen, across all screens in the app)

When the child UIViewController is created and pushed on to view hierarchy (I'm using them with 'UINavigationController'), what I see is its placeholder background area peaking through before the masthead view is added as a subview.

I thought about creating unique masthead view for each screen but most of the app's views will share this masthead. Thus managing content changes across all of them seemed complicated and I'm trying to take the simpler route by having 1 instance.

AppDelegate work:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Other prep work, including setup of self.window
    UIViewController *vc = [[ParentViewController alloc] initWithNibName:nil 
                                bundle:[NSBundle mainBundle]];

    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:vc];        

    self.window.rootViewController = navController;
}

The Parent UIViewController implementation:

@interface ParentViewController : UIViewController {}

@implementation ParentViewController()
- (void)viewDidLoad
{
    // The shared controller and its view has already been created and initialized.

    // Adding the masthead to my view
    [self.view addSubview:self.mastheadController.view];
    [super viewDidLoad];
}
- (void)showChildController
{
    DetailViewController *detailController = [[DetailViewController alloc] initWithNibName:nil
                           bundle:[NSBundle mainBundle]                                                                                 
                           withMastheadController:self.mastheadController];

    [self.navigationController pushViewController:detailController animated:YES];
    detailController = nil;
}

Here's Child UIViewController implementation:

@interface DetailViewController : UIViewController {}

@implementation DetailViewController()
- (void)willMoveToParentViewController:(UIViewController *)parent
{
    // Since this method is invoked before our viewDidLoad and the 
    // parent's viewWillDisappear, remove shared view from parent view 
    // stack.
    [self.mastheadController.view removeFromSuperview];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Adding the shared masthead controller view to our view
    [self.view addSubview:self.mastheadController.view];                         
}

The reason I'm using willMoveToParentViewController is because I thought that if I wait until 'viewWillDisappear' gets called for the ParentViewController, it was not enough time for the mastheadView to get inserted into the child view hierarchy without any noticeable effects.

This is my understanding about the order in which the view appear/disappear events happen:

child:willMoveToParentViewController (parent will be null upon dismiss)
child:viewDidLoad
parent:viewWillDisappear
child:viewWillAppear

Any help would be greatly appreciated.

回答1:

I would approach this differently. Why not add the view to navController's view, and then remove it when you don't want to see it any more?