Pull to refresh

Comments 13

К сожалению, у первого подхода был явный недостаток: программно создавая кнопку и вешая ее на навигейшен бар, я не смог бы добиться легко стандартной стрелочки и кнопки назад (у меня просто не было этой иконки, она походу берется из стандартных asset-ов (наборов)).


А в чём проблема?

self.navigationController.navigationBar.topItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
вот оплошал, оно со стрелочкой создает)) вроде бы и помню, что когда делал как-то не то вышло, а после уже махнул рукой на попытки — и пошел вторым путем) Может как-то немного не так пытался =) буду теперь в курсе
Почти все методы навигации в данном случае начинаются с приставок push/pop, что-то вроде протолкнуть/вытолкнуть (не как в Git-e антонимы push/pull)

UINavigationController при работе с контроллерами представляет собой стек, отсюда и приставки push/pop.

Спасибо, статья хорошая.
>на 7й прошивке имеется правый свайп interactivePopGestureRecognizer, который позволяет делать переходы назад (он вызывал только метод navigation controller delegate will, из-за чего намертво блочил пользовательское взаимодействие).

Отловить «did» в этом случае можно через transitionCoordinator, подписавшись на завершение транзишена, и в коллбэеке проверив что он не был отменен.
не пробовал пользоваться) методы на завершение транзишена с 7й прошивки, а у меня текущий проект с ios 6 sdk, к тому-же если будет такое поведение только на устройствах с такой вот прошивкой — это будет не слишком хорошо, так как поведение везде должно быть идентичным. Но интересный способ отлавливания
В том-то и суть, как вы сами сказали — на 6 описанной проблемы нет (так как нет interactive transitions), поэтому спокойно можно использовать этот вариант только в code path для iOS 7+.
фак мой мозг

Возникает мысль о том, что раз в приложении начинает происходить _такое_, то подключение этого кода только усугубляет печальное положение дел в проекте.

Раз уж прям заниматься этим вопросом, то вместо таймеров и retain-циклов предпочел бы private api.

В статье говорится, что
Так как анимация по своей сути — действие асинхронное (то есть неизвестен точный момент времени, когда вызовется кусок кода, означающий окончание действия, вследствие чего его невозможно синхронизировать с другими кусками кода.

Но ведь
NSLog(@"animation begin");
[CATransaction begin];
UIViewController *tmp = [UIViewController new];
tmp.view.backgroundColor = [UIColor redColor];
[navigationController pushViewController:tmp animated:YES];
[CATransaction setCompletionBlock:^{
    NSLog(@"animation end");
}];
[CATransaction commit];
разве begin / commit методы здесь служат не для группировки анимаций? При вызове коммита — создается явная транзакция, и на GPU отдельно обрабатывается в отдельном потоке (асинхронно). Разве не?

Проект не мой, на него меня посадили, потому-что другие от него отказывались. Я же пустил тяжелую артиллерию рефакторинга и архитектурных изменений, с багами уж так вышло, но дела идут более менее успешно
if(self.delegate && [self.delegate conformsToProtocol:@protocol(MyProtocol)] && [self.delegate respondsToSelector: @selector(aMethod)]){
        [delegate aMethod];
}

В Obj C не нужно делать проверку на то что объект существует перед тем как послать сообщение.
В этом случае вернется NO.
Зачем проверять что объект поддерживает протокол? Лучше объявить его правильно:
@property (weak, nonatomic) id < MyProtocol> delegate;

Поэтому для optional методов остается так:
if ([delegate respondsToSelector:@selector(aMethod)]){
        [delegate aMethod];
}

Для @required без проверок, метод же и так обязательный:
[delegate aMethod];

[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
Не делайте так. Если endIgnoringInteractionEvents не вызовется потом будет очень сложно понять в чем баг.
Я один раз сталкивался с кодом где это сломалось. Было очень плохо.
Если уж очень надо, выключайте у вью. А лучше все-таки делать проверку по флагу.

Чтобы заблокировать двойные пуши из-за двойных тапов или асинхронных вызовов я бы сначала попробовал проверять контроллер который должен отобразиться на isEqual: с тем что сейчас видимый или с теми что в стеке если необходимо.
Эквивалентность определяем по эквивалентности объекта который нужен контроллеру.
Например для PostViewController это должен быть Post.
А эквивалентность постов проверяем по uid.

Пробовали такой подход?
1) я привел наиболее общий подход проверки перед вызовом метода
2) ранее я тоже писал через weak, но в последнее время в большинстве мест у Apple встречаю запись через assign. Тоже, на самом деле, удивило. Но привел здесь вариант со спецификатором assign
3) если аккуратно использовать метод endIgnoringInteractionEvents — то ничего, а что лочило, пока не довел до ума — такое было. Я не упомянул один недостаток блочить чисто вьюхи. Блокирую таким образом — кнопка back так и останется подсвеченной. Видимо по какой-то причине приходит touchDown, а touchUpInside/touchUpOutside не приходит
4) нет, не пробовал. По правде, даже и не до конца понял суть данного подхода, как его применить
Поясните, пожалуйста, что вы понимаете под экранированием ассинхронного кода. Спасибо!
я имею в виду то, что если сделать определенную манипуляцию над данными во время исполнения асинхронного кода, то мы можем получить в результате, что при дальнейшем исполнении обработаются некорректные данные. С сетевыми запросами, например так. Если во время запроса перейти на другое представление выше в иерархии, то указатель на контроллер высвободится, и в результате мы можем получить где-нибудь эксепшен. Простые блокировки, критические секции и мьютексы не всегда способны решить все проблемы с данными, используемыми одновременно более, чем одним потоком.
То есть вместо я предлагаю в некоторых случаях блокировать некоторые вызовы методов, подвергающие данные изменениям. В случае с анимациями — это пользовательское взаимодействие, блокирование обработчиков событий
Sign up to leave a comment.

Articles