Tengo un UINavigationController (para usar como una página del asistente) que puedo crear mediante programación y necesito mostrar un botón «Cancelar» para cancelar el proceso en cualquier UIViewController.

la Creación de la UINavigationController:

FirstVC *firstVC = [[[FirstVC alloc] initWithNibName:@"FirstPage" bundle:nil] autorelease];
firstVC.delegate = self;

navigationController = [[UINavigationController alloc] initWithRootViewController:firstVC];
[self.view addSubview:navigationController.view];

Agregar Botón Cancelar:

UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelRequestNewLeave:)];
navigationController.topViewController.navigationItem.rightBarButtonItem = cancelButton;
[cancelButton release];

Pero cuando empujo a una segunda página para UINavigationController el botón cancelar no se muestra en la UINavigationBar. Si puedo volver a la primera página, el botón cancelar es de allí. Así que, al parecer, el botón se añade sólo para la primera vista. Creo que es porque no estoy subclases UINavigationController, porque necesito para usarlo en una subvista. Pero no sé cómo configurar el rightBarButtonItem en un UINavigationController que se crea mediante programación.

navigationController.topViewController.navigationItem.rightBarButtonItem = cancelButton;

Alguien puede arrojar una luz sobre esto?

Gracias de antemano.

InformationsquelleAutor Ozay | 2011-06-17

8 Comentarios

  1. 41

    El elemento de navegación es por el controlador de vista. La barra de navegación extrae su contenido a partir de los elementos de navegación de la vista controlador, cuya vista es en la actualidad la estructura, que corresponde a la vista controlador en la parte superior de la navegación del controlador de la pila.

    Básicamente tiene cada controlador de vista a pegar un botón de cancelar en su elemento de navegación. Usted puede hacer cualquiera de los siguientes:

    • Copiar-pegar el código en todos los de la vista de los controladores.
    • Mover el código en una función de utilidad o de clase y llamar a eso.
    • Crear una superclase común para todos los de la vista de los controladores que se encarga de configurar el botón cancelar para sus subclases.
    • Gracias por la aclaración. Voy a ir a por la 3ª opción y crear una superclase.
    • Aunque tardía de un comentario, usted debe evitar proporcionar funcionalidad a las clases a través de un super clase. Más adelante en el desarrollo que podría tener algún controlador de subclases que no iba a «me gusta» para heredar la funcionalidad extra. No sólo eso, el código podría ser más complejo.
    • Gracias por tu explicación sobre la relación entre ViewControllers y NavigationItems. Mi Enfoque sobre botones personalizados que sobrevivir desemboca (controlador de interruptores) como este: * ViewControllers heredar de una BaseViewController. * BaseViewController tiene la propiedad de NSMutableDictionary * Este Diccionario, que mantiene información sobre los Botones que se debería mostrar en NavigationItem. * el BaseViewController actualizaciones de la actual NavigationItems botón set. Tal vez mi BaseViewController serán transferidos por el protocolo. Así que es notificado acerca de cualquier cambio en la configuración de los botones.
    • Si usted no puede tener una superclase común porque se hereda de los diferentes tipos de UIViewControllers dentro de UIKit, tales como UICollectionViewController y UIViewController, dos superclases sería necesario. En su lugar, el método de swizzling viewDidLoad y colocar el código de inicialización no se convierte en una opción viable.
    • cómo vamos a llamar a las acciones de la subclase cuando un navigationitem se pulsa el botón?
    • Eso suena como una pregunta nueva: stackoverflow.com/questions/ask

  2. 22

    También puede subclase UINavigationcontroller y dominen algunos métodos como este:

    - (id)initWithRootViewController:(UIViewController *)rootViewController {
        self = [super initWithRootViewController:rootViewController];
        if (self) {
            [self setCloseButtonToController:rootViewController];
        }
        return self;
    }
    
    - (void)dismissController {
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    
    - (void)setCloseButtonToController:(UIViewController *)viewController {
        UIBarButtonItem *closeItem = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(dismissController)];
        [viewController.navigationItem setRightBarButtonItem:closeItem];
    }
    
    - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
        [super pushViewController:viewController animated:animated];
    
        [self setCloseButtonToController:viewController];
    
    }
    • Gracias. Yo estoy presentando un UINavigationController modal y yo quería tener un simple botón Cancelar para aplicar a todas las pantallas dentro de ella. Al parecer, mi caso de uso es extremadamente difícil de Google y no popular.
    • Me gusta tu estilo! 🙂
    • Y con sotryBoard cómo establecer la willShowViewController para mostrar correctamente el botón ?
    • comprobar esto por favor : stackoverflow.com/questions/30372135/…
  3. 8

    Usted puede en lugar de adoptar la UINavigationControllerDelegate protocolo en la clase que crea la UINavigationController instancia. También puede crear la cancelButton por adelantado y, a continuación, implementar navigationController:willShowViewController:animated: como este,

    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
        viewController.navigationItem.rightBarButtonItem = cancelButton;
    }

    Usted tendrá que recordar a crear y mantener la cancelButton y no la suelte. Esto también significa cancelRequestNewLeave: tendrá que ser un método en la clase que crea la UINavigationController instancia que es lo que es ahora mismo, supongo.

    • No estoy seguro de que es una buena idea poner el mismo BBI en varios bares (el iPad ventana emergente Api permitirá mostrar una vista de un BBI, por lo que presumiblemente sólo debe estar en la pantalla en un lugar al mismo tiempo; no estoy seguro de si BBIs por arte de magia contener referencias a sus padres)
    • El uso de willShowViewController a set botón izquierdo en la vista principal, se invalidará el botón atrás en la navegación de la controladora y cuando usted empuje viewController el botón atrás no va a aparecer de alguna manera para solucionar este problema : stackoverflow.com/questions/30372135/…
  4. 5
    1. crear CommonViewController
    2. crear FirstViewController (se extiende desde CommonViewController)
    3. crear SecondeViewController (se extiende desde CommonViewController)
    4. agregar la función de funciones comunes en el CommonViewController

    como que

    CommonViewController.h

    @interface CommonViewController : UIViewController
    
    -(void) initializeCartBarButton;
    
    @end

    CommonViewController.m

    #import "CommonViewController.h"
    
    @interface CommonViewController ()
    
    @end
    
    @implementation CommonViewController
    
    -(void) initializeCartBarButton {
    
    
        UIBarButtonItem *cartBarButton = [[UIBarButtonItem alloc] init];
        cartBarButton.title = @"cart";
        [cartBarButton setTarget: self];
        [cartBarButton setAction: @selector(goToCart:)];
    
        self.navigationItem.rightBarButtonItem = cartBarButton;
        }
    
    - (IBAction) goToCart:(id)sender {
        NSLog(@"");
      }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        //Do any additional setup after loading the view.
      }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        //Dispose of any resources that can be recreated.
      }
    
    @end

    FirstViewController.h

    #import <UIKit/UIKit.h>
    #import "CommonViewController.h"
    
    @interface FirstViewController : CommonViewController
    
    @end

    FirstViewController.m

    #import "FirstViewController.h"
    
    @interface FirstViewController ()
    
    @end
    
    @implementation FirstViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        [self initializeCartBarButton];
    }
    @end

    SecondViewController.h

    #import <UIKit/UIKit.h>
    #import "CommonViewController.h"
    
    @interface SecondViewController : CommonViewController
    
    @end

    SecondViewController.m

    #import "SecondViewController.h"
    
    @interface SecondViewController ()
    
    @end
    
    @implementation SecondViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        [self initializeCartBarButton];
    }
    @end

    nota: puede agregar el código de initializeCartBarButton en el viewDidLoad de CommonViewController y eliminar esta función de CommonViewController y del niño de la clase

    • mohamad probé tu código funciona bien,pero yo no puedo hacer clic en ese botón de la barra.
    • lo siento por mi respuesta anterior. por favor, pruebe este código agregar este 2 de la línea en initializeCartBarButton función después de: cartBarButton.title = @»carro»; [barButton setTarget: auto]; [barButton setAction: @selector(goToCart:)]; que añadir la función goToCart -(IBAction)goToCart:(id)sender { NSLog(@»»); }
    • sí fue resuelto mohamad gracias u..
    • bienvenidos bienvenidos, en cualquier momento
  5. 3

    Esta es la forma en que lo hice con UINavigationController subclase que es capaz de despedir a todos los viewController empujó dentro de ella.

    class CustomNavigationController: UINavigationController, UINavigationControllerDelegate{
    
        //TODO: Use when we have more right bar button types.
        var rightBarButtonType: RightBarButtonType = .Close
    
        enum RightBarButtonType{
            case Close
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.delegate = self
        }
    
        //MARK: Private Functions
        private func addRightBarButtonTo(viewController: UIViewController){
    
            let barButtonItem: UIBarButtonItem!
            switch self.rightBarButtonType {
            case .Close:
                barButtonItem = UIBarButtonItem(image: UIImage(named: "ic_close_white"), style: .Done, target: self, action: #selector(CustomNavigationController.dismiss(_:)))
    
            }
            viewController.navigationItem.rightBarButtonItem = barButtonItem
        }
    
        //MARK: UINavigationController Delegate
        func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
            self.addRightBarButtonTo(viewController)
        }
    
        @objc func dismiss(sender: AnyObject){
            self.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
        }
    }
  6. 1

    Deberá agregar el botón en cada controlador de vista. Usted puede hacerlo mediante la configuración de una o compartir una entre vista a los controladores (en una medida razonable de la moda). Un buen lugar para añadir el botón está en el método viewDidLoad de la vista de los controladores. Usted puede crear un básico UIViewConteoller subclase para ellos si usted siente que esto se vuelve repetitivo.

  7. 0

    Puede agregar un custom ‘Cancelar’ UIButton directamente a la NavigationBar la vista, en lugar de utilizar el UIBarButtonItem.

    UIButton *cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
    cancelButton.imageView = //Some custom image
    cancelButton.frame = CGRectMake(...);  //Something far to the right.
    [self.navigationController.navigationBar addSubview: cancelButton];

    La manera normal de hacer esto es añadir que el botón cancelar de la navigationItem de cada controlador de vista en su pila de navegación. El enfoque anterior puede hacer que sea más sencilla, permitiendo a escribir menos código, pero es un poco de un hack.

    • Problemas: (1) El botón tiene que enviar su acción a algunos de controlador de vista. Usted tiene que trabajar de lo que VC 1 debe hacer cuando hay 2 VCs más arriba en la pila, y cualquiera de ellos podría estar en un estado indeterminado. (2) La barra de navegación será compartida con la VC que empujó a la VC de la modificación de la barra de navegación de este modo, lo que puede llevar a que el botón Cancelar que aparecen en los lugares donde es inapropiado. (3) Podría no jugar bien con los idiomas RTL. No puedo leer, así que no he jugado un poco con la forma de la interfaz de usuario se reconfigura para ellos.
    • Preocupaciones válidas, como ya he dicho es algo de un hack. Él realmente debe tener cada individuo controlador de vista de añadir su propio Cancelar UIBarButtonItem y responder apropiadamente. No creo que muchas de tus preocupaciones se aplican a él aunque. Lo más probable es que este asistente en algunos modal vista controlador que necesita simplemente para despedir a la hora de Anular es explotado. Esto iba a funcionar, independientemente de su estado.
    • Tienes razón, el asistente se encuentra en un referente de controlador de vista y debe ser desestimado. Pensé que podría ser una forma rápida de hacer esto. Creo que voy a mantenerlo simple, utilizar la herencia para agregar el botón a cada VC.
  8. 0

    Añadir este código en tu rootview método viewDidLoad y aplicar la cancelMethod en rootview controlador.Este estará disponible en todas las vistas de los controladores. usted puede ajustar la ubicación del botón por botón de cambio de marco.Para el cambio de orientación que han de ajustar manualmente la ubicación del botón.

     UIButton *btnCancel = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            [btnCancel addTarget:self
                            action:@selector(cancelMethod)
                  forControlEvents:UIControlEventTouchDown];
            [btnCancel setBackgroundImage:[UIImage imageNamed:@"image"]  
            forState:UIControlStateNormal];
            btnCancel.frame = CGRectMake(280, 27, 45, 25);
    
        [self.navigationController.view addSubview: btnCancel];

Dejar respuesta

Please enter your comment!
Please enter your name here