2011-07-29 124 views
10

我正在研究一个应用程序,在左侧有一个“抽屉”会非常有益。我正在做一些初步的测试,看看我是如何最好地完成这个的,而且我有一些非常基本的麻烦。iOS:滑动UIView开启/关闭屏幕

我的设置
1.我使用的是单视图应用程序模板在Xcode 4
2.要在厦门国际银行的“主/边框”的看法,我添加了2个UIViews(LeftPanel和RightPanel)和一个UIButton(ShowHideButton)。
3.我已将LeftPanel绿色和RightPanel蓝色上色以提高可视性。
4.加载视图时,两个面板均可见,并且UIButton具有“隐藏面板”文本。
5.按下按钮后,LeftPanel应滑出屏幕(向左)并且RightPanel应展开以占据其原始空间以及LeftPanel腾空的空间。
6.此时,ShowHideButton应将其文本更改为“显示面板”。
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(Lion的4 Beta版)崩溃。以下是详细信息(每个崩溃都相同):

/SourceCache/DVTFoundation/DVTFoundation-867/Framework/Classes/FilePaths/DVTFilePath中的ASSERTION FAILURE。米:373 详细说明:空字符串不是有效路径 对象: 方法:+ _filePathForParent:fileSystemRepresentation:长度:allowCreation: 主题:{名称=(空),NUM = 55} 提示:无 回溯: 0 0x00000001068719a6 - [IDEAssertionHandler handleFailureInMethod:对象:文件名:LINENUMBER:MessageFormat中:参数:(在IDEKit) 1 0x0000000105f3e324 _DVTAssertionFailureHandler(在DVTFoundation) 2 0x0000000105edd16f + [DVTFilePath _filePathForParent:fileSystemRepresentation:长度:allowCreation:](在DVTFoundation) 3 0x0000000105edcd4d + [DVTFilePath _filePathForParent:pathString:](在DVTFoundation中) 4 0x0000000105ede141 + [DVTFilePath filePathForPathStrin克:](在DVTFoundation) 5 0x00000001064a8dde - [IDEIndex queryProviderForFile:高优先级:(在IDEFoundation) 6 0x000000010655193b - [IDEIndex(IDEIndexQueries)symbolsMatchingName:inContext的:withCurrentFileContentDictionary:](在IDEFoundation) 7 0x000000010aca6166 __68- [IDESourceCodeEditor symbolsForExpression :INQUEUE:completionBlock:] _ block_invoke_01561(在IDESourceEditor) 8 0x00007fff93fb490a _dispatch_call_block_and_release(在libdispatch.dylib) 9 0x00007fff93fb615a _dispatch_queue_drain(在libdispatch.dylib) 10 0x00007fff93fb5fb6 _dispatch_queue_invoke(在libdispatch.dylib) 11 0x00007fff93fb57b0 _dispatch_worker_thread2(在libdispatch.dylib ) 12 0x00007fff8bb5e3da _pthread_wqthread(在libsystem_c.dylib中) 13 0x00007fff8bb5fb85 start_wqthread(在libsystem_c.dylib)

更新:屏幕快照
面板中显示(启动状态) Panel Shown
面板隐藏(按下按钮后成功转型) Panel Hidden
错误:按下按钮,再次导致故障 Error


回答

11

玩过后有了这一堆,我的头靠在墙上,我终于得出结论,除非我误解了有关块的一些东西,否则我的代码没有错。在调试中遍历我的代码产生了与我预期完全相同的答案,但是在动画块的结尾和完成块的开始之间,EXC_BAD_ACCESS一直弹出。

无论如何,我不确定我的想法在哪里,但我想我可能想尝试在我的动画块之外进行数学计算(用于更改帧)。

猜猜是什么? 它工作!

所以,事不宜迟,下面是我想要的东西的工作代码:

- (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模型,所以我不会惊讶于你在这种情况下获得内存错误的动画环境。