2011-07-29 18 views
10

Pracuję nad aplikacją, w której posiadanie "szuflady" po lewej stronie byłoby bardzo korzystne. Przeprowadzam wstępne testy, aby zobaczyć, jak najlepiej to osiągnąć i mam bardzo podstawowe problemy.iOS: Przesuwanie ekranu włączania/wyłączania UIView

Moja konfiguracja
1. Używam jednego szablonu widoku aplikacji w Xcode 4.
2. do "głównego/granicznego" Zdaniem XIb, w Dodałem 2 UIViews (LeftPanel i RightPanel) i UIButton (ShowHideButton).
3. Zmieniłem kolor LeftPanel na zielony i RightPanel na niebieski, aby ułatwić widoczność.
4. Po załadowaniu widoku oba panele są widoczne, a UIButton ma tekst "Ukryj panel".
5. Po naciśnięciu przycisku, LeftPanel powinien zsunąć się z ekranu (w lewo), a RightPanel powinien się rozwinąć, aby zająć jego pierwotne miejsce oraz miejsce opuszczone przez LeftPanel.
6. W tym momencie ShowHideButton powinien zmienić swój tekst na "Pokaż panel".
7. Po ponownym naciśnięciu przycisku, LeftPanel powinien przesunąć się z powrotem na ekran (od lewej), a RightPanel powinien się zmniejszyć, aby "przywrócić" swoje pierwotne miejsce.
8. W tym momencie ShowHideButton powinien zmienić tekst z powrotem na "Ukryj panel".

Wdrażam animację przy użyciu animateWithDuration:animations:completion:. Do tej pory ekran działa dobrze (bardzo dobrze, faktycznie).

Problem polega na tym, że kiedy próbuję przywrócić LeftPanel "wracam", otrzymuję EXC_BAD_ACCESS. Poniżej zamieściłem mój kod i przyjrzałem się temu, ale naprawdę nie widzę, do czego uzyskuję dostępu (lub czegokolwiek, co powoduje 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 

jestem brakuje czegoś super podstawową? Czy ktokolwiek może pomóc?

Dzięki!

EDIT: Próbowałem 2 więcej rzeczy:
1. Problem wydaje się być związane z przystosowaniem widok off-screen na ekranie, jak wychodząc z LeftPanel off-screen daje mi taki sam problem.
2. Przechodzenie przez kod niezawodnie powoduje awarię Xcode (4 Beta for Lion). Oto szczegóły (takie same dla każdej awarii):

AWARIA ASSERTION w/SourceCache/DVTFoundation/DVTFoundation-867/Framework/Classes/FilePaths/DVTFilePath.M: 373 Dane: pusty łańcuch nie jest ważna trasa obiektu Metoda: + _filePathForParent: fileSystemRepresentation długość: allowCreation: gwintu {nazwa = (zerowy) Num = 55} wskazówki: Brak Ślad: 0 0x00000001068719a6 - [IDEAssertionHandler handleFailureInMethod: obiekt: nazwa: LineNumber: messageFormat: argumenty] (w IDEKit) 1 0x0000000105f3e324 _DVTAssertionFailureHandler (w DVTFoundation) 2 0x0000000105edd16f + [DVTFilePath _filePathForParent: fileSystemRepresentation długość: allowCreation:] (w DVTFoundation) 3 0x0000000105edcd4d + [DVTFilePath _filePathForParent: pathString:] (w DVTFoundation) 4 0x0000000105ede141 + [DVTFilePath filePathForPathStrin g:] (w DVTFoundation) 5 0x00000001064a8dde - [IDEIndex queryProviderForFile: highPriority:] (w IDEFoundation) 6 0x000000010655193b - [IDEIndex (IDEIndexQueries) symbolsMatchingName: InContext: withCurrentFileContentDictionary:] (w IDEFoundation) 7 0x000000010aca6166 __68- [IDESourceCodeEditor symbolsForExpression : inQueue: completionBlock:] _ block_invoke_01561 (w IDESourceEditor) 8 0x00007fff93fb490a _dispatch_call_block_and_release (w libdispatch.dylib) 9 0x00007fff93fb615a _dispatch_queue_drain (w libdispatch.dylib) 10 0x00007fff93fb5fb6 _dispatch_queue_invoke (w libdispatch.dylib) 11 0x00007fff93fb57b0 _dispatch_worker_thread2 (w libdispatch.dylib) 12 0x00007fff8bb5e3da _pthread_wqthread (in libsystem_c.dylib) 13 0x00007fff8bb5fb85 start_wqthread (w libsystem_c.dylib)

Aktualizacja: Screen Shots
panel pokazane (stan startowy) Panel Shown
panel ukryty (udane przejście po naciśnięciu przycisku) Panel Hidden
Błąd: Naciśnięcie przycisku ponownie powoduje niewydolność Error


Odpowiedz

11

Po zabawy z tą garstką i waląc głową w ścianę, doszedłem do wniosku, że mój kod nie jest zły, chyba że źle zrozumiałem coś o blokach. Przejście przez mój kod w debugowaniu dało odpowiedzi dokładnie tak, jak się spodziewałem, ale między końcem bloku animacji a początkiem bloku zakończenia pojawił się EXC_BAD_ACCESS.

W każdym razie, nie jestem pewien, skąd wziąłem pomysł, ale pomyślałem, że mógłbym spróbować wykonać moje obliczenia matematyczne (do zmiany ramek) poza blokiem animacji.

Zgadnij co? IT WORKED!

Więc bez zbędnych ceregieli, oto kod roboczych dla co chciałem:

- (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

Myślę, że katastrofa musiała zrobić z nieokreślonych problemów państwowych można uzyskać z UIKit gdy umieścisz główny wątek pod obciążeniem lub znajdują się w środku przejścia widoku. Gdy pobierzesz swoje wartości do obliczeń matematycznych w bloku animacji i poza blokiem, są one różnymi kontekstami, aby uzyskać dostęp do modelu UIView, więc nie jestem zaskoczony kontekstem animacji, w którym pojawia się błąd pamięci w tym przypadku.