Estoy usando el storyboard para mi aplicación que está utilizando UINavigationController. Me gustaría añadir un cuadro de diálogo de confirmación para el valor predeterminado de nuevo el botón para que el usuario no salga accidentalmente. ¿Hay alguna forma de hacer esto? He descubierto que no puedo acceder al botón atrás cuando se ha creado automáticamente por el UINavigationController.

Alguna idea?

OriginalEl autor mtmurdock | 2011-12-19

6 Comentarios

  1. 22

    Desafortunadamente, no se puede interceptar el botón atrás en este camino. El más cercano fax es el uso de su propio UIBarButtonItem conjunto a la navigationItem.leftBarButtonItem y establecer una acción para mostrar su alerta etc. Tuve un diseñador gráfico crear las imágenes de los botones que se ven como el estándar botón atrás.

    Como un aparte, que yo necesitaba para interceptar el botón atrás por una razón diferente. Os exhorto a reconsiderar esta opción de diseño. Si usted está presentando una vista en la que los usuarios pueden realizar cambios y usted quiere que ellos tengan la opción de guardar o cancelar mi humilde opinión, es mejor usar «Guardar» y «Cancelar» botones vs un botón atrás con una alerta. Alertas generalmente son molestas. Como alternativa, dejar claro que los cambios que los usuarios están haciendo están comprometidos en el momento de hacerlas. Entonces, la cuestión es discutible.

    Así que no es una forma, es sólo que si se conecta a cabo por el accidente de que vas a tener que volver a introducir su información (seguridad de la cosa). Aquí está la cosa, yo no soy de agregar el botón atrás. Su existir de forma predeterminada cuando se utiliza el Guión, UIViewController, y desemboca (que soy yo). Incluso si yo estuviera haciendo algo como el que usted describe ese botón atrás, todavía estaría allí.
    usted todavía puede añadir un leftBarButtonItem a su guión y configurarlo. Que vendría a sustituir el botón atrás.
    No me había dado cuenta de que la configuración de leftBarButtonItem sustituido el botón auto. Ahora me siento tonta. Gracias!
    la suya es la mejor respuesta. He sustituido el botón atrás con un UIBarButtonSystemItemCancel y estoy poping manualmente. También he añadido un UIBarButtonSystemItemSave como rightBarButtonItem. Esta es la más limpia de la solución para cancelar y reemplazar el botón atrás.

    OriginalEl autor XJones

  2. 10

    Cómo he trabajado alrededor de esta situación es mediante el establecimiento de la leftBarButtonItem a la UIBarButtonSystemItemTrash estilo (lo que está inmediatamente obvio que no voy a borrar el elemento de borrador) y la adición de una vista de alerta de confirmar la eliminación. Porque se establece una costumbre leftBarButtonItem no se comporte como un botón de volver atrás, por lo que no automáticamente pop la vista!

    Código:

    - (void)viewDidLoad
    {
        //set the left bar button to a nice trash can
        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash
                                                                                              target:self
                                                                                              action:@selector(confirmCancel)];
        [super viewDidLoad];
    }
    
    - (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
    {
        if (buttonIndex)
        {
            //The didn't press "no", so pop that view!
            [self.navigationController popViewControllerAnimated:YES];
        }
    }
    
    - (void)confirmCancel
    {
        //Do whatever confirmation logic you want here, the example is a simple alert view
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Warning"
                                                        message:@"Are you sure you want to delete your draft? This operation cannot be undone."
                                                       delegate:self
                                              cancelButtonTitle:@"No"
                                              otherButtonTitles:@"Yes", nil];
        [alert show];
    }

    Es realmente tan simple como eso! No veo el gran problema, tbh :p

    Tengo que agregar un descargo de responsabilidad, aunque, haciendo de esta forma se rompe la navegación por defecto el comportamiento y apple podría no como los desarrolladores de hacer esto. Yo no he presentado ninguna de las aplicaciones (de momento) con esta característica, así que no estoy seguro de si apple va a permitir su aplicación en la tienda cuando se hace esto, pero se advirtió 😉

    ACTUALIZACIÓN: Buena noticia, todo el mundo! En el mientras tanto he publicado una app (Appcident) la App Store con este comportamiento en el lugar y que Apple no parece a la mente.

    OriginalEl autor Thomas Vervest

  3. 3

    De hecho, usted puede encontrar el botón de volver Atrás la vista y agregar UITapGestureRecognizer.

    Si usted mira esta imagen:
    Confirmar botón atrás en UINavigationController
    Usando este código:

    @interface UIView (debug)
    - (NSString *)recursiveDescription;
    @end
    
    @implementation newViewController
    ... 
    NSLog(@"%@", [self.navigationController.navigationBar recursiveDescription]);

    Usted puede darse cuenta de cómo encontrar el punto de Vista de la parte Posterior del botón. Es siempre el último en subvistas matriz de la navigationbar.

    2012-05-11 14:56:32.572 backBtn[65281:f803] <UINavigationBar: 0x6a9e9c0; frame = (0 20; 320 44); clipsToBounds = YES; opaque = NO; autoresize = W; layer = <CALayer: 0x6a9ea30>>
    | <UINavigationBarBackground: 0x6aa1340; frame = (0 0; 320 44); opaque = NO; autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x6aa13b0>>
    | <UINavigationButton: 0x6d6dde0; frame = (267 7; 48 30); opaque = NO; layer = <CALayer: 0x6d6d9f0>>
    |    | <UIImageView: 0x6d70400; frame = (0 0; 48 30); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6d6d7d0>>
    |    | <UIButtonLabel: 0x6d70020; frame = (12 7; 23 15); text = 'Edit'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6d6dec0>>
    | <UINavigationItemView: 0x6d6d3a0; frame = (160 21; 0 0); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6d6d3f0>>
    | <UINavigationItemButtonView: 0x6d6d420; frame = (5 7; 139 30); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6d6d4e0>>

    Lo que he usado:

    UIView *backButton = [[navBar subviews] lastObject];
    [backButton setUserInteractionEnabled:YES];
    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(alertMsg)];
    [tapGestureRecognizer setNumberOfTapsRequired:1];
    [backButton addGestureRecognizer:tapGestureRecognizer];

    Pulsando en el botón atrás y voilà:
    Confirmar botón atrás en UINavigationController

    Interesante. Tengo un par de dudas. ¿Qué garantía tengo de que el botón atrás siempre será el último objeto? Y lo hace añadiendo un gesto de reconocimiento de quitar el comportamiento predeterminado, o simplemente añadir una segunda acción?
    1. No hay garantía 🙂 2. Añadir gesto de reconocimiento omite todos los otros gestos.
    Bueno, si no hay ninguna garantía de entonces no es una buena solución. Si Apple cambia algo en su código para cambiar el orden de los botones en la lista, entonces mi aplicación va a romper y voy a tener un error difícil de rastrear.
    He encontrado que UITapGestureRecognizer es bastante inútil. No maneje el caso de que un usuario podría toque y mantenga en una vista y, a continuación, suelte. En su lugar, por lo general sólo utiliza un UILongPressGestureRecognizer con el minimumPressDuration conjunto de propiedades a 0.0. De esta forma, se encarga tanto de las escuchas y largo pulsando un botón.
    Nunca hacer este tipo de subvista-matriz-hack! Su aplicación podría romper con las nuevas versiones de iOS y no es que fácil de entender para otras personas de la lectura de su código. Tal vez no es un problema de ahora, sino más adelante. Thomas Vervest y @XJones respuesta es el camino correcto a seguir.

    OriginalEl autor mafonya

  4. 1

    Aquí es una solución: (Probado en iOS10 y 11)

    Agregar toque gesto de reconocimiento a la barra de navegación:

    let tap = UITapGestureRecognizer(target: self, action: #selector(onBackPressed(gestureRecognizer:)))
    tap.cancelsTouchesInView = true
    self.navigationController?.navigationBar.addGestureRecognizer(tap)

    cancelsTouchesInView = true asegura que el botón atrás no obtiene el evento táctil.

    Manejar el gesto:

    @objc func onBackPressed(gestureRecognizer: UITapGestureRecognizer) {
    guard gestureRecognizer.location(in: gestureRecognizer.view).x < 100 else {
    return
    }
    //... back button is pressed do what you wanted to

    Lugar de utilizar 100 como número mágico usted puede encontrar la vista que contiene el botón atrás y utilizar el marco de detectar toques.

    OriginalEl autor ELO8C8

  5. 0

    Aquí es lo que usted necesita hacer para hacer fácilmente una costumbre botón que reproduce el aspecto de la predeterminada del botón atrás en el iPhone y el iPad, con el código escrito de forma explícita porque me imagino que va a venir aquí en busca de nuevo en algún momento.

    Poner las siguientes funciones en algún lugar de la aplicación (.m) archivo de la correspondiente UIViewController con un UINavigationController y, a continuación, en viewDidLoad ejecutar [self setupBackButton];

    Lo que te gustaría hacer con el botón atrás, poner en el backButtonPressed función.

    - (void)setupBackButton {
    UIImage *leftArrowImage;
    UIImage *pressedLeftArrowImage;
    UIButton *customBackButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 48, 30)];
    [customBackButton setAutoresizingMask:UIViewAutoresizingNone];
    customBackButton.titleLabel.font=[UIFont boldSystemFontOfSize:12];
    [customBackButton setTitle:@"Back" forState:UIControlStateNormal];
    [customBackButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled];
    [customBackButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 5, 0, 0)];
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    leftArrowImage = [UIImage imageNamed:@"UINavigationBarSilverBack.png"];
    pressedLeftArrowImage = [UIImage imageNamed:@"UINavigationBarSilverBackPressed.png"];
    }
    else {
    leftArrowImage = [UIImage imageNamed:@"UINavigationBarDefaultBack.png"];
    pressedLeftArrowImage = [UIImage imageNamed:@"UINavigationBarDefaultBackPressed.png"];
    }
    UIImage *stretchableLeftArrowImage = [leftArrowImage stretchableImageWithLeftCapWidth:15.0 topCapHeight:0];
    UIImage *stretchablePressedLeftArrowImage = [pressedLeftArrowImage stretchableImageWithLeftCapWidth:15.0 topCapHeight:0];
    [customBackButton setBackgroundColor:[UIColor clearColor]];
    [customBackButton setBackgroundImage:stretchableLeftArrowImage forState:UIControlStateNormal];
    [customBackButton setBackgroundImage:stretchablePressedLeftArrowImage forState:UIControlStateHighlighted];
    [customBackButton addTarget:self action:@selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *aCustomBackButtonItem = [[UIBarButtonItem alloc] initWithCustomView:customBackButton];
    [[self navigationItem] setLeftBarButtonItem:aCustomBackButtonItem];
    }
    - (void)backButtonPressed:(id)sender {
    NSLog(@"back button pressed");
    }

    Obtener el exacto botón png de iOS, recomiendo la UIKit Obras De Arte Extractor. Después de ejecutar el proyecto y guardar las imágenes en el iPad Retina simulador seguido por el iPad no-retina simulador, buscar los títulos en el ‘Común’ en la carpeta del simulador de la carpeta que aparece en su escritorio. Los nombres de archivo «UINavigationBar…de nuevo(@2x).png» y «UINavigationBar…BackPressed(@2x).png» son lo que usted desea.

    Estoy adjuntando también el por defecto iOS (iPhone y iPad) de nuevo el botón de la barra png utilizado en el código anterior como una conveniencia. Tenga en cuenta que con las actualizaciones de iOS, la mirada de el valor predeterminado de la barbuttonitems puede cambiar…

    y ha cambiado…
    Votada abajo como esta ha quedado obsoleto por iOS7 y hasta

    OriginalEl autor Victor Van Hee

  6. 0

    Easy peasy. Cubrir sólo el botón con un transparente UIControl y la captura de los toques.

    - (void)viewDidAppear:(BOOL)animated
    {
    [super viewDidAppear:animated];
    #define COVER_HEIGHT    44
    //make this an iVar:  UIControl *backCover;
    if ( backCover == nil ) {
    CGRect cFrame = CGRectMake( 0, self.view.frame.origin.y-COVER_HEIGHT, 100, COVER_HEIGHT);
    backCover = [[UIControl alloc] initWithFrame:cFrame]; //cover the back button
    backCover.backgroundColor = [[UIColor orangeColor] colorWithAlphaComponent:0.2]; //transparent
    //use clearColor later
    [backCover addTarget:self action:@selector(backCoverAction:)
    forControlEvents:UIControlEventTouchDown];
    [self.view.window addSubview:backCover];
    }
    }
    - (void)viewWillDisappear:(BOOL)animated
    {
    [super viewWillDisappear:animated];
    [backCover removeFromSuperview]; //prevent coverage on another view
    backCover = nil;
    }
    - (void)backCoverAction:(UIControl *)sender
    {
    //decide what to do -- maybe show a dialog.
    //to actually go "Back" do this:
    [self.navigationController popViewControllerAnimated:YES]; //"Back"
    }

    Este esquema también funciona para tabBar botones, pero es más complejo de determinar la ubicación.

    OriginalEl autor Jeff

Dejar respuesta

Please enter your comment!
Please enter your name here