iOS:滑动UIView开/关屏幕

我正在开发一个应用程序,在左侧有一个“抽屉”将是非常有益的。 我正在做一些初步的testing,看看我是如何最好的完成这个,我有一些非常基本的麻烦。

我的设置
1.我在Xcode 4中使用单视图应用程序模板。
2.到xib的“main / border”视图中,我添加了2个UIViews(LeftPanel和RightPanel)和一个UIButton(ShowHideButton)。
3.我已将LeftPanel绿色和RightPanel蓝色着色,以便于查看。
4.加载视图时,两个面板均可见,并且UIButton具有“隐藏面板”文本。
5.按下button后,LeftPanel应滑出屏幕(向左),并且RightPanel应展开以占据其原始空间加上LeftPanel空出的空间。
6.此时,ShowHideButton应将其文本更改为“显示面板”。
7.再次按下button时,LeftPanel应该滑回到屏幕上(从左边),RightPanel应该收缩以将其原始空间“缩回”。
8.此时,ShowHideButton应将其文本更改回“隐藏面板”。

我正在使用animateWithDuration:animations:completion:实现animationanimateWithDuration:animations:completion: 。 到目前为止, closures屏幕的转换工作正常(实际上很好)。

令我感到困扰的是,当我尝试将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 

我是否缺less超基本的东西? 任何人都可以帮忙吗?

谢谢!

编辑:我已经尝试了2件事情:
1.这个问题似乎与在屏幕上显示离屏视图有关,因为从LeftPanel开始离屏给我提出了同样的问题。
2.通过代码可靠地导致Xcode(Lion的4 Beta)崩溃。 这里是细节(每次崩溃都是一样的):

/SourceCache/DVTFoundation/DVTFoundation-867/Framework/Classes/FilePaths/DVTFilePath.m:373中的ASSERTION FAILURE详细信息:空string不是有效path对象:方法:+ _filePathForParent:fileSystemRepresentation:length:allowCreation:Thread:{name = (在IDEKit中)1 0x0000000105f3e324 _DVTAssertionFailureHandler(在DVTFoundation中)2 0x0000000105edd16f + [DVTFilePath _filePathForParent:fileSystemRepresentation(null),num = 55} Hints:None Backtrace:0 0x00000001068719a6 – [IDEAssertionHandler handleFailureInMethod:object:fileName:lineNumber:messageFormat: (在DVFFoundation中)5 0x00000001064a8dde – [IDEIndex queryProviderForFile:highPriority:](在IDEFoundation中):length:allowCreation:](在DVTFoundation中)3 0x0000000105edcd4d + [DVTFilePath _filePathForParent:pathString:](在DVTFoundation中)4 0x0000000105ede141 + [DVTFilePath filePathForPathString: 6 0x000000010655193b – [IDEIndex(IDEIndexQueries)symbolsMatchingName:inContext:withCurrentFileContentDictionary:](在IDEFoundation中)7 0 x000000010aca6166 __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中)

更新:屏幕截图
面板显示(启动状态) 面板显示
面板隐藏(按下button后成功转换) 面板隐藏
错误:再次按下button会导致失败 错误


在玩了这一堆东西之后,我把头撞在墙上,最后得出结论,除非我误解了有关块的一些东西,否则我的代码没有错。 在debugging中遍历我的代码得到的答案与我期望的完全一致,但是在animation块的结尾和完成块的开始之间,EXC_BAD_ACCESS一直popup。

无论如何,我不知道我的想法是什么,但我想我可能想尝试在我的animation块之外进行math计算(用于更改帧)。

你猜怎么了? 有效!

所以,不要紧张,这是我想要的工作代码:

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

我认为你的崩溃必须处理你可以通过UIKit获得的不确定的状态问题,无论何时加载主线程或处于视图转换的中间。 当你在animation块中获取你的数值计算值,或者在块外部时,他们是不同的上下文来访问UIView模型,所以在这种情况下,在animation上下文中你会遇到内存错误。

Interesting Posts