iOS: скольжение UIView вкл / выкл экран - PullRequest
10 голосов
/ 29 июля 2011

Я работаю над приложением, в котором наличие «ящика» на левой стороне было бы очень полезно.Я провожу некоторые начальные тесты, чтобы увидеть, как мне лучше всего это сделать, и у меня возникли некоторые базовые проблемы.

Моя настройка 1. Я использую шаблон приложения с одним представлением в Xcode 4.2. К представлению xib «main / border» я добавил 2 UIViews (LeftPanel и RightPanel) и UIButton (ShowHideButton).3. Я покрасил зеленый цвет левой панели и синий цвет правой панели для лучшей видимости.4. Когда представление загружено, обе панели видны, а на кнопке UIB есть текст «Скрыть панель».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. Проблема, по-видимому, связана с выводом на экран вне экрана, так как запуск с левой стороны вне экрана дает мне ту же проблему.2. Надежное выполнение кода приводит к сбою Xcode (4 Beta for Lion).Вот подробности (одинаковые для каждого сбоя):

СБОЙ АССЕРТИВНОСТИ в /SourceCache/DVTFoundation/DVTFoundation-867/Framework/Classes/FilePaths/DVTFilePath.m:373 Подробности: пустая строка не является допустимым объектом путиМетодIDEKit) 1 0x0000000105f3e324 _DVTAssertionFailureHandler (в DVTFoundation) 2 0x0000000105edd16f + [DVTFilePath _filePathForParent: fileSystemRepresentation: длина: allowCreation:] (в DVTFoundation) 3 0x0000000105edcd4d + [DVTFilePath _filePathForParent: pathString:] (в DVTFoundation) 4 0x0000000105ede141 + [DVTFilePath filePathForPathString:] (в DVTFoundation) 5 0x00000001064a8dde - [IDEIndex queryProviderForFile: highPriority:] (в IDEFoundation) 6 0x000000010655193b - [IDEIndex (IDEIndexQueries) символыMatchingName: 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 0x00007fff8bb5fb30 *Показанная панель (состояние запуска) Panel ShownПанель скрыта (успешный переход после нажатия кнопки) Panel HiddenОшибка: повторное нажатие кнопки вызывает сбой Error


Ответы [ 2 ]

11 голосов
/ 29 июля 2011

Поиграв с этой кучей и ударившись головой о стену, я, наконец, пришел к выводу, что мой код не ошибся, если я что-то не понял в блоках. Пройдя по моему коду в отладке, мы получили ответы, точно такие, как я ожидал, но между концом блока анимации и началом блока завершения продолжал появляться 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 голосов
/ 26 октября 2012

Я думаю, что ваш сбой был связан с неопределенными проблемами состояния, которые вы можете получить с UIKit, когда вы загружаете основной поток или находитесь в середине перехода представления.Когда вы извлекаете свои значения для своего математического вычисления в блоке анимации и вне блока, это разные контексты для доступа к модели UIView, поэтому я не удивлен, что в контексте анимации вы получаете ошибку памяти в этом случае.

...