24

I have an activity view that I have added in AppDelegate class to tap bar:

[self.mainTabBar.view addSubview: spinner];

When there are connection problems it is visible in each view controller and is spinning. There is some button at certain view controller, makes to present some modal view controller. That modal view controller overlaps the spinner. How to make that spinner always be on top of all views or at least on top of that modal view controller? I tried to make such a thing in view controller that presents modal view controller:

[self presentModalViewController:selectionViewController animated:YES];
[self.view bringSubviewToFront:[self.tabBarController.view viewWithTag:15]];

Not works.

nik
  • 417
  • 1
  • 6
  • 13

4 Answers4

65

Add the view to the main window.

UIWindow* mainWindow = [[UIApplication sharedApplication] keyWindow];
[mainWindow addSubview: spinner];
Felix
  • 35,041
  • 12
  • 93
  • 141
12

While phix23's answer is correct, here is a more complete example:

//The view you want to present
UIViewController *viewControllerYouWantToPresentOnTop = [[UIViewController alloc] initWithNibName:nil bundle:nil];

//Create transparent host view for presenting the above view
UIWindow* mainWindow = [[UIApplication sharedApplication] keyWindow];
UIViewController *viewControllerForPresentation = [[UIViewController alloc] init];
[[viewControllerForPresentation view] setBackgroundColor:[UIColor clearColor]];
[[viewControllerForPresentation view] setOpaque:FALSE];
[mainWindow addSubview:[viewControllerForPresentation view]];

//Make your transparent view controller present your actual view controller
[viewControllerForPresentation presentViewController:viewControllerYouWantToPresentOnTop animated:TRUE];

Remember to clean up after yourself when you don't need these any longer.

This code can be used from anywhere in your app, even a library :)

Maciej Swic
  • 10,562
  • 8
  • 46
  • 64
4

An app normally displays its content within a single window throughout its life. But there are situations where an extra window may be used to add content on top of everything else. Apple ensures UIAlertView always stays on top by adding it in a separate window.

UIView *contentView = [[UIView alloc] initWithFrame:contentFrame];
contentView.backgroundColor = [UIColor greenColor];
UIWindow *window = [[UIWindow alloc] initWithFrame:CGRectMake(x,y,contentFrame.size.width, contentFrame.size.height)];
window.windowLevel = UIWindowLevelAlert;
[window addSubview:contentView];
[window makeKeyAndVisible];

Show and hide your window by setting window.hidden = Yes or No as needed. This will always show your contentView on top of everything else in the app.

NobodyNada
  • 7,002
  • 6
  • 39
  • 48
0

The modal controller is in a completely different layer, you cannot make any subview of the presenting controller to overlap it.

Use a UIAlertView with a spinner inside. The alerts are displayed in a layer which overlaps even modal controllers.

Sulthan
  • 118,286
  • 20
  • 194
  • 245
  • This is not true. While alert views are in a separate layer on top of everything else, modals are not and can be overridden using the code i posted below. – Maciej Swic Nov 20 '12 at 09:12
  • @MaciejSwic I know how to add subviews to window, note that my answer was stating `any subview of the presenting controller`. Using `UIAlertView` is technically a better solution. – Sulthan Nov 20 '12 at 10:25