10

私は、左側に「引き出し」があると非常に有益なアプリに取り組んでいます。私はこれをどのように達成するのが最善かを確認するためにいくつかの初期テストを行っていますが、非常に基本的な問題があります。

セットアップ
1.Xcode4 でシングルビューアプリケーションテンプレートを使用しています
。2。xibの「メイン/ボーダー」ビューに、2つのUIView(LeftPanelとRightPanel)とUIButton(ShowHideButton)を追加しました。
3.見やすくするために、LeftPanelを緑、RightPanelを青に色付けしました。
4.ビューがロードされると、両方のパネルが表示され、UIButtonに「HidePanel」というテキストが表示されます。
5.ボタンを押すと、LeftPanelが画面からスライドして(左に)移動し、RightPanelが拡張して、元のスペースとLeftPanelによって空いたスペースを占有します。
6.この時点で、ShowHideButtonはテキストを「ShowPanel」に変更する必要があります。
7.ボタンをもう一度押すと、LeftPanelが(左から)画面にスライドして戻り、RightPanelが縮小して元のスペースを「元に戻す」必要があります。
8.この時点で、ShowHideButtonはテキストを「HidePanel」に戻す必要があります。

を使用してアニメーションを実装していanimateWithDuration:animations:completion:ます。これまでのところ、画面からの移行は正常に機能しています(実際には非常にうまくいきます)。

私が困っているのは、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)がクラッシュします。詳細は次のとおりです(すべてのクラッシュで同じ)。

/SourceCache/DVTFoundation/DVTFoundation-867/Framework/Classes/FilePaths/DVTFilePath.m:373のアサーションの失敗詳細:空の文字列は有効なパスではありませんオブジェクト:メソッド:+ _ filePathForParent:fileSystemRepresentation:length:allowCreation:スレッド:{名前= (null)、num = 55}ヒント:なしバックトレース:0 0x00000001068719a6-[IDEAssertionHandler handleFailureInMethod:object:fileName:lineNumber:messageFormat:arguments:](IDEKit内)1 0x0000000105f3e324 _DVTAssertionFailureHandler(DVTFoundation内)2 0x0000000105ed :length:allowCreation:](DVTFoundation内)3 0x0000000105edcd4d + [DVTFilePath _filePathForParent:pathString:](DVTFoundation内)4 0x0000000105ede141 + [DVTFilePath filePathForPathString:](DVTFoundation内)5 0x00000001064a8dde-[IDEIndex queryProviderhighPriority:](IDEFoundation内)6 0x000000010655193b-[IDEIndex(IDEIndexQueries)symbolsMatchingName:inContext:withCurrentFileContentDictionary:](IDEFoundation内)7 0x000000010aca6166 __68-[IDESourceCodeEditor symbolForExpression:inQueue:completionBlock:] _ block_invoke_01561(in IDE .dylib)libdispatch.dylib 9 0x00007fff93fb615aの_dispatch_queue_drain()10 0x00007fff93fb5fb6 _dispatch_queue_invoke(libdispatch.dylibで)libdispatch.dylib 11 0x00007fff93fb57b0 _dispatch_worker_thread2()12 0x00007fff8bb5e3da _pthread_wqthread(libsystem_c.dylibで)libsystem_c.dylib 13 0x00007fff8bb5fb85 start_wqthread()withCurrentFileContentDictionary:] 7 0x000000010aca6166 __68- [IDESourceCodeEditor symbolsForExpression(IDEFoundationで):inQueue:completionBlock:] _ block_invoke_01561(中IDESourceEditor)8 0x00007fff93fb490a _dispatch_call_block_and_release(中libdispatch.dylib)9 0x00007fff93fb615a _dispatch_queue_drain(INは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内)withCurrentFileContentDictionary:] 7 0x000000010aca6166 __68- [IDESourceCodeEditor symbolsForExpression(IDEFoundationで):inQueue:completionBlock:] _ block_invoke_01561(中IDESourceEditor)8 0x00007fff93fb490a _dispatch_call_block_and_release(中libdispatch.dylib)9 0x00007fff93fb615a _dispatch_queue_drain(INは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内)dylib)libdispatch.dylib 9 0x00007fff93fb615aの_dispatch_queue_drain()10 0x00007fff93fb5fb6 _dispatch_queue_invoke(libdispatch.dylibで)libdispatch.dylib 11 0x00007fff93fb57b0 _dispatch_worker_thread2()12 0x00007fff8bb5e3da _pthread_wqthread(libsystem_c.dylibで)libsystem_c.dylib 13 0x00007fff8bb5fb85 start_wqthread()dylib)libdispatch.dylib 9 0x00007fff93fb615aの_dispatch_queue_drain()10 0x00007fff93fb5fb6 _dispatch_queue_invoke(libdispatch.dylibで)libdispatch.dylib 11 0x00007fff93fb57b0 _dispatch_worker_thread2()12 0x00007fff8bb5e3da _pthread_wqthread(libsystem_c.dylibで)libsystem_c.dylib 13 0x00007fff8bb5fb85 start_wqthread()

更新:スクリーンショット
パネル表示(起動状態) 示されているパネル
パネル非表示(ボタンを押した後の遷移の成功) パネル非表示
エラー:ボタンをもう一度押すと失敗します エラー


4

2 に答える 2

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;
    }
}
于 2011-07-29T19:28:48.843 に答える
0

あなたのクラッシュは、メインスレッドに負荷をかけたり、ビューの遷移の途中にあるときはいつでもUIKitで発生する可能性のある不確定な状態の問題に関係していたと思います. 数学的計算の値をアニメーション ブロック内とブロック外で取得する場合、それらは UIView モデルにアクセスするための異なるコンテキストであるため、その場合にメモリ エラーが発生するアニメーション コンテキストには驚きません。

于 2012-10-25T23:36:33.913 に答える