Hacer que un button persista en todos los controlleres de vista

Quiero tener un button persistente en la esquina inferior derecha de mi aplicación. Durante todas las transiciones de vista, el button debe permanecer estático. Tengo problemas para decidir a qué vista agregar el button. Sé que el button debe savese en AppDelegate, pero no sé qué otra vista tendría sentido agregarlo excepto la window. Una desventaja de agregarlo a la window es que cuando hay una aplicación ejecutándose en segundo plano (es decir, teléfono), el relleno de la barra de estado agregado empujará hacia abajo la window. En general, agregarlo a la window parece ser una solución hacky, ¿alguna idea?

Sí, agregarlo a UIWindow sería extremadamente hacky y fastidioso.

Guiones charts

Si está utilizando Storyboards y iOS 5.0 en adelante, debería poder usar vistas de contenedor y hacer algo como esto:

EL BOTÓN MAH ESTÁ ENCANTADO

Aquí hay otra image que muestra la estructura, bastante simplist, del primer controller de vista:

introduzca la descripción de la imagen aquí

El controller de vista de la izquierda tiene un contenedor y luego una vista que contiene el button encima de él. El contenedor indica que el controller de navigation (directamente a la derecha) debe aparecer dentro de sí mismo, esa relación se muestra mediante la flecha =([])=> (formalmente conocida como una inserción segura ). Finalmente, el controller de navigation define su controller de vista raíz al que está a la derecha.

En resumen, la primera vista del control de panqueques: en la vista del contenedor con el button en la parte superior, para que todo lo que sucede dentro tenga que tener el button en la parte superior.

Usando childViewControllers

aka El modo "Odio los Storyboards y los cachorros"

Utilizando una estructura similar a la versión Storyboard, puede crear el controller de vista base con su button y, a continuación, agregar la vista que se convertirá en la nueva "raíz" de la aplicación, debajo.

Para dejar en claro, llamemos al controller de vista que contiene el button FakeRootViewController , y al controller de vista que será, a todos los fines prácticos, la raíz de la aplicación: RootViewController . Todos los controlleres de vista subsiguientes ni siquiera sabrán que está el FakeRootViewController encima de todos los demás.

FakeRootViewController.m

 // The "real" root #import "RootViewController.h" // Call once after the view has been set up (either through nib or coded). - (void)setupRootViewController { // Instantiate what will become the new root RootViewController *root = [[RootViewController alloc] <#initWith...#>]; // Create the Navigation Controller UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:root]; // Add its view beneath all ours (including the button we made) [self addChildViewController:nav]; [self.view insertSubview:nav.view atIndex:0]; [nav didMoveToParentViewController:self]; } 

AppDelegate.m

 #import "FakeRootViewController.h" - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; FakeRootViewController *fakeRoot = [[FakeRootViewController alloc] <#initWith...#>]; self.window.rootViewController = fakeRoot; [self.window makeKeyAndVisible]; return YES; } 

De esa manera, puede tener todos los beneficios de insert el button en la window, sin la culpa y "¿Debo ser realmente un progtwigdor?" que causa

Potencialmente, podría tener un controller de vista principal "raíz", y todos los demás controlleres de vista podrían ser controlleres de vista secundarios, con sus vistas como vistas secundarias. Luego tendrían su contenido, y el button estaría en el controller de vista "raíz". Pero esto parece tan incompleto e hacky como ponerlo en la window, y probablemente less conveniente.

Yo uso este button:

 @interface UIPopUpButton : UIImageView <UIPopoverControllerDelegate, UIActionSheetDelegate> { UIPopoverController* popoverController; Class popoverClass; } - (id) initWithPoint: (CGPoint) point; - (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event; + (id) buttonAtPoint: (CGPoint) point; + (id) buttonAtOriginalPoint; + (void) unhighlight; + (void) bringButtonToFront; @property (nonatomic, retain) UIPopoverController* popoverController; @property (nonatomic, assign) Class popoverClass; @end #import "UIPopUpButton.h" @implementation UIPopUpButton static UIPopUpButton* button = nil; static CGPoint originalPoint; @synthesize popoverClass; @synthesize popoverController; + (id) buttonAtPoint: (CGPoint) point { if (button == nil) { button = [[UIPopUpButton alloc] initWithPoint: point]; originalPoint = point; button.popoverClass = [UIPopoverController class]; } else { button.frame = CGRectMake(point.x, point.y, button.frame.size.width, button.frame.size.height); } return button; } + (id) buttonAtOriginalPoint { return [self buttonAtPoint: originalPoint]; } + (void) unhighlight { button.highlighted = NO; } + (void) bringButtonToFront { [[UIApplication shanetworkingApplication].keyWindow addSubview: [self buttonAtOriginalPoint]]; } - (id) initWithPoint: (CGPoint) point { UIImage* image1 = [UIImage imageNamed: @"topbutton.png"]; UIImage* image2 = [UIImage imageNamed: @"topbutton.png"]; if ((self = [super initWithImage: image1 highlightedImage: image2])) { self.userInteractionEnabled = YES; self.frame = CGRectMake(point.x, point.y, self.frame.size.width, self.frame.size.height); self.multipleTouchEnabled = NO; } return self; } - (BOOL) isAppCurrStatus { return ([DevToolsClientController shanetworkingInstance].statusOfRootViewController == FrontEndApplication); } - (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event { UITouch* touch = [touches anyObject]; if(touch.view == self) { if (self.popoverController == nil) { if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { UIActionSheet* actionSheet = [[UIActionSheet alloc] initWithTitle: @"Please choice operation:" delegate: self cancelButtonTitle: nil destructiveButtonTitle: nil otherButtonTitles: nil]; [actionSheet addButtonWithTitle: @"Cancel"]; actionSheet.cancelButtonIndex = 0; [actionSheet addButtonWithTitle: @"Button 1"]; actionSheet.actionSheetStyle = UIActionSheetStyleDefault; [actionSheet setTag: 0]; [actionSheet setDelegate: self]; [actionSheet showInView: [self superview]]; [actionSheet release]; [actions release]; } else { PopoverMenuController* contentViewController = [[PopoverMenuController alloc] init]; self.popoverController = [[UIPopoverController alloc] initWithContentViewController: contentViewController]; popoverController.delegate = self; [popoverController presentPopoverFromRect: CGRectMake(10.0f, 10.0f, 5.0f, 5.0f) inView: self permittedArrowDirections: UIPopoverArrowDirectionAny animated: YES]; contentViewController.popoverController = self.popoverController; [contentViewController reloadData]; } } else { [self.popoverController dismissPopoverAnimated:YES]; self.popoverController = nil; } } [super touchesBegan: touches withEvent: event]; } #pragma mark UIActionSheetDelegate implementation -(void) actionSheet: (UIActionSheet*) actionSheet clickedButtonAtIndex: (NSInteger) buttonIndex { NSNumber* indexAction = [[NSNumber alloc] initWithInt: buttonIndex - 1]; } - (void) runAction: (NSNumber*) indexAction { [DevToolsPopoverMenuController runAction: [indexAction integerValue]]; } #pragma mark - #pragma mark UIPopoverControllerDelegate implementation - (void) popoverControllerDidDismissPopover: (UIPopoverController*) thePopoverController { if (self.popoverController != nil) { self.popoverController = nil; } } - (BOOL) popoverControllerShouldDismissPopover: (UIPopoverController*) thePopoverController { //The popover is automatically dismissed if you click outside it, unless you return NO here return YES; } @end 

llamada:

  [UIPopUpButton bringButtonToFront]; 

Mi button siempre está en la parte superior.

Prueba subclassando la class UIViewController y crea la tuya propia con el button

Cree un object singleton que contenga el button para que todos los controlleres de vista puedan hacer reference a él y agregarlo a su subvista o agregarlo directamente a la window.

 SomeClass.h @property (nonatomic) UIButton *yourButton; +(SomeClass*)shanetworkingSomeClass; SomeClass.m @synthesize yourButton = _yourButton; -(id)init { self = [super init]; if(self) { _yourButton = [UIButton new]; //Other settings you want for your button } return self; } +(SomeClass)shanetworkingSomeClass { static SomeClass *shanetworkingSomeClass; if (!shanetworkingSomeClass) shanetworkingSomeClass = [[super allocWithZone:nil]init]; return shanetworkingSomeClass; } +(void)allocWithZone:(NSZone*)zone { return [self shanetworkingSomeClass]; } 

Si lo deseas, puedes acceder a la window directamente así:

 UIWindow *mainwindow = [[[UIApplication shanetworkingApplication]delegate]window]; 

importe SomeClass.h a sus controlleres de vista y acceda al button desde cualquier lugar

 #import "SomeClass.h" SomeClass *someClass = [SomeClass shanetworkingSomeclass]; UIButton *localButton = someClass.yourButton;