2011-07-29 16 views
10

Estoy trabajando en una aplicación donde tener un "cajón" en el lado izquierdo sería muy beneficioso. Estoy haciendo algunas pruebas iniciales para ver cómo lograría esto, y estoy teniendo problemas muy básicos.iOS: Pantalla de activación/desactivación de UIView deslizante

mi configuración
1. Estoy usando una plantilla de aplicación de una sola vista en Xcode 4.
2. "/ frontera principal" opinión de la xib, he añadido 2 UIViews (LeftPanel y RightPanel) y un UIButton (ShowHideButton).
3. Coloreé el panel izquierdo verde y el azul derecho para una mejor visibilidad.
4. Cuando se carga la vista, ambos paneles son visibles y el UIButton tiene el texto "Ocultar panel".
5. Al presionar el botón, LeftPanel debería deslizarse fuera de la pantalla (a la izquierda) y RightPanel debería expandirse para ocupar su espacio original más el espacio dejado por LeftPanel.
6. En este punto, ShowHideButton debería cambiar su texto a "Mostrar panel".
7. Al presionar el botón nuevamente, LeftPanel debe deslizarse hacia atrás en la pantalla (desde la izquierda) y RightPanel debe contraerse para "devolverlo" a su espacio original.
8. En este punto, ShowHideButton debería cambiar su texto de nuevo a "Ocultar panel".

Estoy implementando la animación usando animateWithDuration:animations:completion:. Hasta ahora, la transición OFF la pantalla está funcionando bien (muy bien, en realidad).

Lo que me preocupa es que cuando trato de devolver LeftPanel "de nuevo", obtengo un EXC_BAD_ACCESS. He publicado mi código a continuación, y lo he visto, pero realmente no puedo ver a qué estoy accediendo que ha sido liberado (o lo que está causando el EXC_BAD_ACCESS).

DrawerTestingViewController.h 
#import <UIKit/UIKit.h> 

typedef enum { 
    kHidden, 
    kShown 
} PanelState; 

@interface DrawerTestingViewController : UIViewController { 

    PanelState currentState; 

    UIButton *showHideButton; 

    UIView  *leftPanel; 
    UIView  *rightPanel; 
} 

@property (assign, nonatomic)   PanelState CurrentState; 

@property (strong, nonatomic) IBOutlet UIButton  *ShowHideButton; 

@property (strong, nonatomic) IBOutlet UIView  *LeftPanel; 
@property (strong, nonatomic) IBOutlet UIView  *RightPanel; 

- (IBAction)showHidePressed:(id)sender; 

@end 


DrawerTestingViewController.m 
#import "DrawerTestingViewController.h" 

@implementation DrawerTestingViewController 

@synthesize CurrentState = currentState; 
@synthesize LeftPanel  = leftPanel; 
@synthesize RightPanel  = rightPanel; 
@synthesize ShowHideButton = showHideButton; 

#pragma mark - My Methods 

- (IBAction)showHidePressed:(id)sender 
{ 
    switch ([self CurrentState]) { 
     case kShown: 
      // Hide the panel and change the button's text 
      // 1. Hide the panel 
      [UIView animateWithDuration:0.5 
       animations:^{ 
       // b. Move left panel from (0, 0, w, h) to (-w, 0, w, h) 
       CGRect currLeftPanelRect = [[self LeftPanel] frame]; 
       currLeftPanelRect.origin.x = -1 * currLeftPanelRect.size.width; 
       [[self LeftPanel] setFrame:currLeftPanelRect]; 
       // c. Expand right panel from (x, 0, w, h) to (0, 0, w + x, h) 
       CGRect currRightPanelRect = [[self RightPanel] frame]; 
       currRightPanelRect.origin.x = 0; 
       currRightPanelRect.size.width += currLeftPanelRect.size.width; 
       [[self RightPanel] setFrame:currRightPanelRect];} 
       completion:NULL]; 
      // 2. Change the button's text 
      [[self ShowHideButton] setTitle:@"Show Panel" forState:UIControlStateNormal]; 
      // 3. Flip [self CurrentState] 
      [self setCurrentState:kHidden]; 
      break; 
     case kHidden: 
      // Show the panel and change the button's text 
      // 1. Show the panel 
      [UIView animateWithDuration:0.5 
       animations:^{ 
       // b. Move left panel from (-w, 0, w, h) to (0, 0, w, h) 
       CGRect currLeftPanelRect = [[self LeftPanel] frame]; 
       currLeftPanelRect.origin.x = 0; 
       [[self LeftPanel] setFrame:currLeftPanelRect]; 
       // c. Expand right panel from (0, 0, w, h) to (leftWidth, 0, w - leftWidth, h) 
       CGRect currRightPanelRect = [[self RightPanel] frame]; 
       currRightPanelRect.origin.x = currLeftPanelRect.size.width; 
       currRightPanelRect.size.width -= currLeftPanelRect.size.width; 
       [[self RightPanel] setFrame:currRightPanelRect];} 
       completion:NULL]; 
      // 2. Change the button's text 
      [[self ShowHideButton] setTitle:@"Hide Panel" forState:UIControlStateNormal]; 
      // 3. Flip [self CurrentState] 
      [self setCurrentState:kShown]; 
      break; 
     default: 
      break; 
    } 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    [self setCurrentState:kShown]; 
} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    switch ([self CurrentState]) { 
     case kShown: 
      [[self ShowHideButton] setTitle:@"Hide Panel" forState:UIControlStateNormal]; 
      break; 
     case kHidden: 
      [[self ShowHideButton] setTitle:@"Show Panel" forState:UIControlStateNormal]; 
      break; 
     default: 
      break; 
    } 
} 

@end 

Me estoy perdiendo algo súper básica? ¿Alguien puede ayudar?

Gracias!

Editar: He intentado 2 cosas más:
1. El problema parece estar relacionado con lo que la vista fuera de la pantalla en la pantalla, ya que a partir de LeftPanel fuera de la pantalla me da la el mismo problema.
2. Recorrer el código de manera confiable hace que se bloquee Xcode (4 Beta for Lion). Aquí están los detalles (lo mismo para cada bloqueo):

FALLO DE LA ASSERCIÓN en/SourceCache/DVTFoundation/DVTFoundation-867/Framework/Classes/FilePaths/DVTFilePath.m: 373 Detalles: cadena vacía no es un válido camino objeto: Método: + _filePathForParent: fileSystemRepresentation: longitud: allowCreation: Tema: {name = (null), num = 55} Hints: Ninguno Backtrace: 0 0x00000001068719a6 - [IDEAssertionHandler handleFailureInMethod: objeto: Nombre del archivo: LineNumber: MessageFormat: argumentos:] (en IDEKit) 1 0x0000000105f3e324 _DVTAssertionFailureHandler (en DVTFoundation) 2 0x0000000105edd16f + [DVTFilePath _filePathForParent: fileSystemRepresentation: longitud: allowCreation:] (en DVTFoundation) 3 0x0000000105edcd4d + [DVTFilePath _filePathForParent: pathString:] (en DVTFoundation) 4 0x0000000105ede141 + [DVTFilePath filePathForPathStrin g:] (en DVTFoundation) 5 0x00000001064a8dde - [IDEIndex queryProviderForFile: highPriority:] (en IDEFoundation) 6 0x000000010655193b - [IDEIndex (IDEIndexQueries) symbolsMatchingName: InContext: withCurrentFileContentDictionary:] (en IDEFoundation) 7 0x000000010aca6166 __68- [IDESourceCodeEditor symbolsForExpression : INQUEUE: completionBlock:] _ block_invoke_01561 (en IDESourceEditor) 8 _dispatch_call_block_and_release 0x00007fff93fb490a (en libdispatch.dylib) 9 _dispatch_queue_drain 0x00007fff93fb615a (en libdispatch.dylib) 10 0x00007fff93fb5fb6 _dispatch_queue_invoke (en libdispatch.dylib) 11 0x00007fff93fb57b0 _dispatch_worker_thread2 (en libdispatch.dylib) 12 0x00007fff8bb5e3da _pthread_wqthread (en libsystem_c.dylib) 13 0x00007fff8bb5fb85 start_wqthread (en libsystem_c.dylib)

Actualización: Pantallas
Panel Hidden
error panel que se muestra (estado de inicio) Panel Shown
panel oculto (transición exitosa después de pulsar el botón): Al pulsar de nuevo el botón provoca el fracaso Error


Respuesta

11

Después de jugar con este grupo y golpeando mi cabeza contra la pared, finalmente llegué a la conclusión de que mi código no estaba mal a menos que malinterpretara algo sobre bloques. Pasando por mi código en depuración obtuve las respuestas exactamente como esperaba, pero entre el final del bloque de animación y el comienzo del bloque de finalización, una EXC_BAD_ACCESS siguió apareciendo.

De todos modos, no estoy seguro de dónde saqué la idea, pero pensé que podría querer hacer mis cálculos matemáticos (para cambiar los marcos) fuera de mi bloque de animación.

¿Adivina qué? ¡FUNCIONÓ!

Así, sin más preámbulos, aquí está el código de trabajo para lo que quería:

- (IBAction)showHidePressed:(id)sender 
{ 
    switch ([self CurrentState]) { 
     case kShown: 
     { 
      // Hide the panel and change the button's text 
      CGRect currLeftPanelRect = [[self LeftPanel] frame]; 
      currLeftPanelRect.origin.x -= currLeftPanelRect.size.width/2; 
      CGRect currRightPanelRect = [[self RightPanel] frame]; 
      currRightPanelRect.origin.x = 0; 
      currRightPanelRect.size.width += currLeftPanelRect.size.width; 
      // 1. Hide the panel 
      [UIView animateWithDuration:0.5 
       animations:^{ 
       // b. Move left panel from (0, 0, w, h) to (-w, 0, w, h) 
       [[self LeftPanel] setFrame:currLeftPanelRect]; 
       // c. Expand right panel from (x, 0, w, h) to (0, 0, w + x, h) 
       [[self RightPanel] setFrame:currRightPanelRect]; 
       } 
       completion:^(BOOL finished){ if(finished) { 
       [[self ShowHideButton] setTitle:@"Show Panel" forState:UIControlStateNormal]; 
       [self setCurrentState:kHidden]; 
       } 
       }]; 
     }    
      break; 
     case kHidden: 
     { 
      // Show the panel and change the button's text 
      // 1. Show the panel 
      [UIView animateWithDuration:0.5 
       animations:^{ 
       // b. Move left panel from (-w, 0, w, h) to (0, 0, w, h) 
       CGRect currLeftPanelRect = [[self LeftPanel] frame]; 
       currLeftPanelRect.origin.x += currLeftPanelRect.size.width/2; 
       [[self LeftPanel] setFrame:currLeftPanelRect]; 
       // c. Expand right panel from (0, 0, w, h) to (leftWidth, 0, w - leftWidth, h) 
       CGRect currRightPanelRect = [[self RightPanel] frame]; 
       currRightPanelRect.origin.x = currLeftPanelRect.size.width; 
       currRightPanelRect.size.width -= currLeftPanelRect.size.width; 
       [[self RightPanel] setFrame:currRightPanelRect]; 
       } 
       completion:^(BOOL finished){ if(finished) { 
       [[self ShowHideButton] setTitle:@"Hide Panel" forState:UIControlStateNormal]; 
       [self setCurrentState:kShown]; 
       } 
       }]; 
     } 
      break; 
     default: 
      break; 
    } 
} 
0

creo que el accidente tuvo que ver con los problemas de estado indeterminado, usted puede obtener con UIKit cada vez que se pone el hilo principal bajo carga o están en el medio de una transición de vista. Cuando recupera sus valores para su cálculo matemático en el bloque de animación vs fuera del bloque, son contextos diferentes para acceder al modelo UIView, por lo que no me sorprende en el contexto de la animación que obtenga un error de memoria en ese caso.

Cuestiones relacionadas