Кратенько напишу, что делает код выше:
1. Подписка на 2 нотификации: показать/скрыть прогресс бар, кстати нотификации абсолютно бесполезные, если мы говорим о синглтоне, в любом месте можно дёрнуть соотвествующий метод.
2. Показываем прогресс бар (showProgressBar)
2.1. Добавление затемнения и анимация 0.3 сек
2.2. Добавление белой плашки прогресс бара и анимация 0.3 сек
2.3. Добавление серого зипа к белой плашки
2.4. Добавление контейнера оранжего зипа и картинки оранжевого зипа (ох сколько вьюшек, хотя надо было использовать просто backgroundColor) и сразу же (!) анимация на 15 секунд.
3. Скрываем, если пришла нотификация
3.1 Анимация скрытия вьюшек за 0.3 сек (альфа и белая плашка вертикально)
И никаких быстренько потом добежать до конца нет.
Думаю вы сами ответили на свой вопрос. В данной статье (предположим с плохим соединением) прогресс бар через 15 секунд покажет что задача выполнена 100%, но при этом экран полностью заблокирован. Такое приложение пользователи сочтут глюкавым и тормознутым. Вообще, не хорошо блокировать экран, когда можно выпонять задачу в параллельном потоке.
Логика прогресс бара как раз не в том, чтобы показывать фейк 15 секунд, в результате которого пользователь может ничего не получить, а наоборот подтверить что работа идёт и он отображает данный прогресс. Для отправки SMS/iMessage используется несколько состояний прогресс бара:
1. Задачу менеджер отправки сообщений принял, определил в очередь и проверяет доступность сети/интернета.
2. Если связь есть, то в зависимость от типа связи соответствующие тайминги на прогресс отправки, но это не 100% прогресс бара.
3. Когда сообщение отправлено или связи нет включается финальная анимация завершения работы.
Нет самого главного, свойства progress.
Если говорить про отрисовку, то вариантов масса. Я бы скорее всего отрисовал через CAShapeLayer, но если и использовать картинки, то здесь очевидно что можно использовать паттерн, который легко масштабирется и может быть любой длинны (UIColor colorWithPatternImage).
Если говорить об анимации, то не совсем понятно зачем столько блоков анимации фейдинга, когда с одними и теми же таймингами. И нет отмены анимаци, если необходимо перезапустить анимацию с другими параметрами, это когда дело дойдёт до конкретного использования данного класса.
И раз уж каждый раз создаются вьюшки после removeFromSuperview надо очищать переменную, которая ссылается на эту вьюшку.
Про стиль написания кода можно многое сказать, но всё же пару заметок:
— не надо использовать префикс k для констант и именование лучше делать по формуле ИмяКлассИмяКонстанты;
— не надо использовать define для констант, вместо этого: extern NSString *const BSBeautifulProgressBarManagerShowProgressBarNotification;
— приватные переменные _всегда_ реализовывать через свойства приватной категории;
— всегда использовать фигурные скобки в if, а то знаете что бывает (return return);
— флоат числа определять как флоат: 0.5f
Книга классика для Objective-C разработчиков, странно, что издательства до сих пор не взялись её перевести, она будет актуально ещё долгое время. Про декоратор также отличный пример на Objective-C комбинации протокола, категории и forwardingTargetForSelector от NSObject.
За перевод спасибо! Теперь, я так думаю, ждём паттерн «Стратегия».
При тестировании данной фичи я написал апп, который показывал локальную нотификацию всякий раз, когда система запускала backgroundFetch, а параметр minimumBackgroundFetchInterval = UIApplicationBackgroundFetchIntervalMinimum. За пару дней обычного использования айфона при наличии Wi-Fi апп запускается в фоне несколько раз в день. Иногда подряд около 5-10 раз с интервалом 10-20 мин.
Есть ещё один момент, если возвращать через completionHandler значение UIBackgroundFetchResultNewData, то система будет считать, что вы сохранили новые данные и скорее всего ваш UI тоже будет выглядеть по новому и соответственно скриншот аппа в списке задач устарел. Поэтому, по не понятным правилам, но апп будет отдельно запущен в фоновым режиме для перегенерации скриншота. Поэтому апп Погоды «всегда» показывает актуальную температуру на скриншоте в списке задач.
Спасибо автору за статью и последованное изложение, погружение в KVO, для начинающих это клад.
По аналогии реализовал класс KVO всё отлично работает. По рекомендации с сеттером пришлось написать ещё небольшой макрос, который собственно и генерирует сеттер с вызовом метода stopObservation. Также по моим задачам пришлось добавить возможность следить за несколькими keyPath с одним блоком обработки, но после этого возникла необходимоть в блоке сразу передавать конкретно keyPath, для которого сработало событие. И для блока лучше сразу сделать определение в хидере класса, так удобнее его указывать в параметрах и в случае чего менять сигнатуру.
Игра интересная, поздравляю! Правда пока вы будете делать левелпаки не думали ли вы, что другая подготовленная команда реализует версию под iOS/Android и снимут все сливки?
Обратите внимание на Macbook Pro/Air и забудете о других буках. Матовые есть у Pro, но глянец это дополнительная защита из специального стекла. Я сам правда сижу на макбуке с матовым экраном, но всё больше и больше смотрю в сторону Air, тем более скоро будет обновление линейки Air на Sandy Bridge. Air больше всего подкупает своим весом 1.32кг с матрицей 13" при 1440x900 и время автономной работы 7 часов (!). А вопрос выбора операционной системы с интеловскими процессорами уже не актуален, можно установить всё что угодно. Конечно, не пиарить не получается, когда покупка макбук решила много вопросов уже на несколько лет и можно спокойно работать.
1. Подписка на 2 нотификации: показать/скрыть прогресс бар, кстати нотификации абсолютно бесполезные, если мы говорим о синглтоне, в любом месте можно дёрнуть соотвествующий метод.
2. Показываем прогресс бар (showProgressBar)
2.1. Добавление затемнения и анимация 0.3 сек
2.2. Добавление белой плашки прогресс бара и анимация 0.3 сек
2.3. Добавление серого зипа к белой плашки
2.4. Добавление контейнера оранжего зипа и картинки оранжевого зипа (ох сколько вьюшек, хотя надо было использовать просто backgroundColor) и сразу же (!) анимация на 15 секунд.
3. Скрываем, если пришла нотификация
3.1 Анимация скрытия вьюшек за 0.3 сек (альфа и белая плашка вертикально)
И никаких быстренько потом добежать до конца нет.
1. Задачу менеджер отправки сообщений принял, определил в очередь и проверяет доступность сети/интернета.
2. Если связь есть, то в зависимость от типа связи соответствующие тайминги на прогресс отправки, но это не 100% прогресс бара.
3. Когда сообщение отправлено или связи нет включается финальная анимация завершения работы.
Если говорить про отрисовку, то вариантов масса. Я бы скорее всего отрисовал через CAShapeLayer, но если и использовать картинки, то здесь очевидно что можно использовать паттерн, который легко масштабирется и может быть любой длинны (UIColor colorWithPatternImage).
Если говорить об анимации, то не совсем понятно зачем столько блоков анимации фейдинга, когда с одними и теми же таймингами. И нет отмены анимаци, если необходимо перезапустить анимацию с другими параметрами, это когда дело дойдёт до конкретного использования данного класса.
И раз уж каждый раз создаются вьюшки после removeFromSuperview надо очищать переменную, которая ссылается на эту вьюшку.
Про стиль написания кода можно многое сказать, но всё же пару заметок:
— не надо использовать префикс k для констант и именование лучше делать по формуле ИмяКлассИмяКонстанты;
— не надо использовать define для констант, вместо этого: extern NSString *const BSBeautifulProgressBarManagerShowProgressBarNotification;
— приватные переменные _всегда_ реализовывать через свойства приватной категории;
— всегда использовать фигурные скобки в if, а то знаете что бывает (return return);
— флоат числа определять как флоат: 0.5f
Цель статьи какая?
За перевод спасибо! Теперь, я так думаю, ждём паттерн «Стратегия».
Есть ещё один момент, если возвращать через completionHandler значение UIBackgroundFetchResultNewData, то система будет считать, что вы сохранили новые данные и скорее всего ваш UI тоже будет выглядеть по новому и соответственно скриншот аппа в списке задач устарел. Поэтому, по не понятным правилам, но апп будет отдельно запущен в фоновым режиме для перегенерации скриншота. Поэтому апп Погоды «всегда» показывает актуальную температуру на скриншоте в списке задач.
iOS 7 Tech Talk Videos / Hidden iOS 7 Development Gems
По аналогии реализовал класс KVO всё отлично работает. По рекомендации с сеттером пришлось написать ещё небольшой макрос, который собственно и генерирует сеттер с вызовом метода
stopObservation
. Также по моим задачам пришлось добавить возможность следить за несколькими keyPath с одним блоком обработки, но после этого возникла необходимоть в блоке сразу передавать конкретно keyPath, для которого сработало событие. И для блока лучше сразу сделать определение в хидере класса, так удобнее его указывать в параметрах и в случае чего менять сигнатуру.typedef void (^ETRKVOBlock)(ETRKVO *kvo, NSDictionary *change));
…
@property (nonatomic, copy) ETRKVOBlock block;
…
- (id)initWithSubject:(id)subject keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(ETRKVOBlock)block;
результат: