2011-07-29 3 views
10

왼쪽에 '서랍'이있는 것이 효과가있는 앱에서 작업하고 있습니다. 어떻게하면이 일을 가장 잘 수행 할 수 있는지를 알기 위해 초기 테스트를하고 있는데, 아주 기본적인 문제가 있습니다.iOS : 슬라이딩 UIView 켜기/끄기 화면

내 설정 내가 XIB의 "기본/경계"보기에
2. 엑스 코드 4에 단일보기 응용 프로그램 템플릿을 사용하고

1. 나는 2 UIViews (LeftPanel 및 RightPanel) 추가했습니다 및 UIButton (ShowHideButton)이 있습니다.
3. 시력을 좋게하기 위해 LeftPanel 녹색과 RightPanel을 파란색으로 칠했습니다.
4.보기가로드되면 두 패널 모두 표시되고 UIButton의 텍스트는 "패널 숨기기"입니다.
5. 버튼을 누르면 LeftPanel이 화면에서 벗어나 (왼쪽으로) RightPanel이 확장되어 원래 공간과 LeftPanel에 의해 비워진 공간을 차지합니다.
6.이 시점에서 ShowHideButton은 텍스트를 "Show Panel"로 변경해야합니다.
7. 버튼을 다시 누르면 LeftPanel이 화면 (왼쪽부터)로 돌아가고 RightPanel이 축소되어 원래 공간으로 돌아갑니다.
8.이 시점에서 ShowHideButton은 텍스트를 다시 "패널 숨기기"로 변경해야합니다.

animateWithDuration:animations:completion:을 사용하여 애니메이션을 구현 중입니다. 지금까지 화면 전환은 OFF입니다. (실제로는 아주 좋았습니다.)

내가 좌지우지 할 때 LeftPanel을 "뒤로"가져 오려고 할 때 EXC_BAD_ACCESS가 표시됩니다. 내가 아래에 내 코드를 게시했습니다, 그리고 그것을 봤어,하지만 난 정말 그게 공개 된 (또는 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 


나는 슈퍼 기본 뭔가를 놓치고 있습니까? 아무도 도와 줄 수 있니?

고마워요!

편집 : 내가 해봤 2 가지 더 :
1. 문제 나야을 제공 오프 스크린 LeftPanel로 시작으로, 화면 오프 화면보기를 데려 관련이있을 것으로 보인다 같은 문제.
2. 코드를 단계별로 실행하면 Xcode (4 Beta for Lion)가 충돌합니다. 자세한 내용은 다음과 같습니다 (모든 충돌시 동일).

ASSERTION FAILURE in/SourceCache/DVTFoundation/DVTFoundation-867/Framework/Classes/FilePaths/DVTFilePath.m : 373 개 세부 사항 : 역 추적 없음 : 방법 : : + _filePathForParent : fileSystemRepresentation : 길이 : allowCreation : 스레드 : {이름 = (널), NUM = 55} 힌트 빈 문자열이 유효한 경로 객체가 아닌 경우 0 0x00000001068719a6 - [IDEAssertionHandler handleFailureInMethod : 개체 : 파일명 : LINENUMBER : MessageFormat의 : 인자들 : (DVTFoundation)에 1 0x0000000105f3e324 _DVTAssertionFailureHandler 2 0x0000000105edd16f + (IDEKit에서) : fileSystemRepresentation : 길이 allowCreation : DVTFilePath _filePathForParent (DVTFoundation)에 3 0x0000000105edcd4d + [DVTFilePath _filePathForParent : pathString :] (DVTFoundation에서) 4 0x0000000105ede141 + [DVTFilePath filePathForPathStrin g : (DVTFoundation)에 0x00000001064a8dde 5 - [IDEIndex queryProviderForFile : highPriority 규정 :] 6 0x000000010655193b (IDEFoundation에서) - symbolsMatchingName [IDEIndex (IDEIndexQueries) inContext :] 7 0x000000010aca6166 __68- [IDESourceCodeEditor symbolsForExpression (IDEFoundation 내) withCurrentFileContentDictionary : INQUEUE : completionBlock :] _ libdispatch.dylib에서 (libdispatch.dylib)에 8 0x00007fff93fb490a의 _dispatch_call_block_and_release (libdispatch.dylib)에서 9 0x00007fff93fb615a의 _dispatch_queue_drain (libdispatch.dylib)에 10 0x00007fff93fb5fb6 _dispatch_queue_invoke 11 0x00007fff93fb57b0 _dispatch_worker_thread2 (IDESourceEditor)에 block_invoke_01561 () 12 0x00007fff8bb5e3da _pthread_wqthread (libsystem_c.dylib에 있음)(libsystem_c.dylib에서)(13) 0x00007fff8bb5fb85 start_wqthread

업데이트 : 스크린 샷
패널 표시됨 (시작 상태) Panel Shown
패널 숨겨진 (버튼을 누른 후 성공적인 전환) Panel Hidden
오류 : 누르면 버튼을 다시 실패 Error


답변

11

장난 후에 발생 이 뭉치와 내 머리를 벽에 치고, 블록에 대해 오해하지 않는 한 마침내 결론을 내 코드가 잘못되지 않았다. 디버그에서 내 코드를 실행하면 예상했던 것과 똑같은 대답을 얻을 수 있었지만 애니메이션 블록이 끝날 때와 완료 블록이 시작될 때 EXC_BAD_ACCESS가 계속 나타났습니다.

어쨌든 아이디어를 얻은 곳이 어디인지 모르겠지만 애니메이션 블록 외부에서 수학 계산 (프레임 변경)을 시도하고 싶을 수도 있습니다.

어째서? IT WORKED!

그래서, 속히, 여기에 내가 원하는 것을하기위한 작업 코드는 다음과 같습니다

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

나는 당신의 충돌이 메인 스레드를 넣을 때마다 UIKit으로 얻을 수있는 불확실한 상태 문제를 함께 할 수 있다고 생각 로드 중이거나 뷰 전환의 중간에 있습니다. 애니메이션 블록에서의 수학적 계산 값을 블록 외부에서 검색하면 UIView 모델에 액세스하는 데 다른 컨텍스트가 적용되므로 애니메이션 컨텍스트에서 메모리 오류가 발생하더라도 놀라지 않습니다.