Перевести поток в спящий режим, но сохранить анимацию — возможно ли это?

#ios #uitableview #animation #uisearchdisplaycontroller

#iOS #uitableview #Анимация #uisearchdisplaycontroller

Вопрос:

Это может быть странный вопрос, но может быть другое решение для того, чего я пытаюсь достичь, я открыт для всего, что работает по мере необходимости!

Факты:

У меня есть a UITableView с a UISearchBar , обрабатываемый a UISearchDisplayController .

Выше указанного TableView у меня есть несколько кнопок и маленький UIScrollView .

Когда пользователь нажимает на панель поиска и появляется клавиатура, для отображения результатов поиска во время ввода остается очень мало места.

Поэтому я хочу переместить TableView полностью наверх (закрыв кнопки и ScrollView), когда пользователь начинает поиск.

Мой код и проблема:

 - (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
...

[UIView beginAnimations:@"Search" context:nil];
[UIView setAnimationDuration:0.6];
[self.attractionsTableView setFrame:CGRectMake(0, 0, 320, 400)];
[UIView commitAnimations];

...
return;
  

}

Теперь проблема в том, что, поскольку расстояние, которое я UITableView должен пройти, составляет около 100 точек, searchDisplayController работает быстрее, помещая черное наложение поверх TableView, и, таким образом, черное наложение уже находится сверху, в то время как TableView все еще скользит туда.

В результате получается экран, который выглядит примерно так:

проблема http://img833.imageshack.us/img833/9186/problemqdu.png

Таким образом, пользователь видит, что TableView скользит вверх (что было бы хорошо), но черное наложение уже там, потому что анимация searchDisplayController быстрее, чем у меня.

Итак, у меня есть возможная идея, но я не знаю, как это сделать:

Есть ли способ установить продолжительность анимации searchDisplayController, поместив черное наложение поверх таблицы поиска?

Редактировать:

Я знаю, что могу установить для animationDuration значение 0.01 или даже 0, но скорость 0.6 кажется вполне приемлемой для расстояния в 100 точек, поэтому я пытаюсь найти другое решение, которое уменьшает продолжительность.

Ответ №1:

Хитрость заключается в том, чтобы не позволять циклу выполнения работать нормально, пока ваша анимация не будет выполнена. Анимации выполняются, когда цикл выполнения выполняется в определенном режиме. К счастью, анимация наложения выполняется в другом режиме цикла выполнения, чем другие анимации, которые выполняются в режиме цикла выполнения по умолчанию. Итак, все, что вам нужно сделать, это запустить цикл выполнения из вашего метода, пока анимация не будет завершена.

 - (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
    BOOL done = NO;
    // Pass the done variable's address as the context so we can be notified
    [UIView beginAnimations:@"SearchExpand" context:amp;done];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(animationDone:finished:context:)];
    [UIView setAnimationDuration:0.6];
    // Expend the table view to fill its superview
    self.attractionsTableView.frame = [[self.attractionsTableView superview] bounds];
    [UIView commitAnimations];
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    // Run the run loop until the animation completes
    while(!done) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        if(![runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]])
            break;
        [pool drain];
    }
}

- (void)animationDone:(NSString *)name finished:(NSNumber *)finished context:(void *)context {
    // Set the done flag to YES
    *((BOOL*)context) = YES;
    // and kill the run loop
    CFRunLoopStop(CFRunLoopGetCurrent());
}
  

Комментарии:

1. работает как шарм! удивительно! 🙂 ты мужик! Однако один вопрос: для чего используется аргумент (NSNumber *)finished в методе (void)animationDone?

2. Еще один вопрос: есть ли какая-либо документация по этому поводу? Потому что я вроде бы понял это, но я не думаю, что мог бы использовать это в каком-либо другом контексте. И есть ли способ узнать, выполняется ли анимация в этом «другом режиме цикла выполнения»?

3. Третий вопрос (извините).. Я не понимаю, почему мы создаем новый NSAutoreleasePool в цикле while. Я просто попытался прокомментировать это, чтобы, возможно, найти исключение, которое помогло бы мне понять, для чего оно, но оно все еще работает без пула. Это плохой код или я создал утечку памяти или что-то в этом роде?

4. @Octoshape finished Аргумент будет содержать YES , завершена ли анимация и NO была ли она остановлена. Анимация, выполняемая в другом режиме, не документирована. Я узнал методом проб и ошибок. Пул авторелиза — это, по сути, мера безопасности, поскольку вы не знаете, что произойдет в цикле выполнения. Может быть сгенерирован значительный объем автоматически освобождаемой памяти.

5. Это абсолютно ЛУЧШЕЕ решение, которое я когда-либо видел для решения проблемы с пользовательским интерфейсом! 🙂 Слава за «наплевать». 🙂