Вообще, по-моему ещё в 2018 уже было или даже раньше. Точно знаю что был натив тк при мне оно было. С годами могу чуть ошибиться, но когда в 2019 уходил оно уже точно в доступе было
Симуляция нужна только при дебаге, убедится что все работает как надо.
Про погрешность я уже писал, зато вспомнил благодаря комментарию о "авиарежиме", отсутствии симкарты и блокировке GPS, что дописал в "интересные моменты".
Да, большое спасибо, недоглядел. Использование в таком виде allowDeferredLocationUpdates в принципе бесполезно было, по статье и коду убрал, текст дополнил.
Код писался с максимально простотой, по этому отсутствует обработка ошибок в принципе didFailWithError / didFinishDeferredUpdatesWithError (CLError.h).
Про то что allowDeferredLocationUpdates вызывается до didUpdateLocations:
Start the delivery of location updates before calling this method.
Соблюдено, CLLocationManager уже запущен. didUpdateLocations это не старт менеджера, первый вызов метода может быть и спустя пару минут, что наблюдал на практике.
Другое дело, что обычно allowDeferredLocationUpdates вызывается из didUpdateLocations, потому что в документации дальше следует:
After processing any new locations, call this method if you want to defer future updates until the distance or time criteria are met.
p.s. большое спасибо за комментарий, попутно вспомнил и поправил в статье, что я забыл о нюансах allowDeferredLocationUpdates и выпилил использование из примера ибо влиять в том использовании не должно было.
p.p.s. статью писал почти через 9 месяцев "не работы" с геолокацией, немного подзабыть успел, надеюсь никому не навредил "бесполезным" куском кода.
Начнет проигрывать файл только по требованию, просто можно указать сразу запускать или не сразу (все там же в настройках схемы).
Про скорость вот тут можно глянуть.
Provide one or more waypoints containing a latitude/longitude pair. If you provide one waypoint, Xcode will simulate that specific location. If you provide multiple waypoints, Xcode will simulate a route visitng each waypoint.
Optionally provide a time element for each waypoint. Xcode will interpolate movement at a rate of speed based on the time elapsed between each waypoint. If you do not provide a time element, then Xcode will use a fixed rate of speed. Waypoints must be sorted by time in ascending order.
Про точки и промежутки не понял вопроса, метод вызывается когда новые данные появились (обычно в массиве 1 элемент, но к примеру при использовании `defer` в массиве все точки что накопились)
swift от objc классов остается практически тем же objc только с другим синтаксисом, по этому почему бы и не использовать логику работы objc для улучшения.
Когда весь проект на swift, много чистых swift элементов, то тут и начинается проявляться проблема «оберток» о которой я упомянул, но похоже забыл написать в статье. Это относится к различию между Any и AnyClass когда надо в prepareForSegue передавать данные.
К тому же если принять соглашение к именованию контроллеров в сториборде как сам класс, то можно используя небольшую модификацию вместо идентификатора передавать класс и получать в замыкание уже приведенный экземпляр класса (не писать постоянно as! в замыкании)
сегодня оптимизацией кода разбирался тк надоело смотреть на долгую компиляцию
первым делом написан был скрипт на башике, который делал файл с тем что компилится больше 1мс (потом увеличил до 50) и выводит суммарное время сборки.
Результат ~ 32'000ms
Прошерстил 2 функции (flatMap цепочка одна фунция и убрал lazy в другом месте) и уже 20'000ms
Еще 2 функции перебрал и уже 18сек компиляция
Собственно всего то разнес во временные переменные результаты
Даже если все сделать на переменных (Variable, PropertyType), то в них всеравно придется биндить сигналы (не скажу в этом случае за rx, но в rac это создаст Disposable и его нужно будет положить в composite (bag)). И всеравно ViewModel будет иметь по этому bag, по этому не вижу ничего плохого если будет подписка на сигналы не только во ViewController.
Кстати, если все перевести в такие переменные, сложно сопоставлять будет действия когда придет новый человек. А вот если сервисы выдают сигналы и на них подписываются из Presentation (ViewModel к примеру и потом выдает результат по необходимости в Controller на обновления) то сложного ничего нет, потому что разделяются обязанности: сервис сконфигурировал, ViewModel подготовил данные и обновился Controller
Биндинга между моделью и вьюмоделью не делаем, сервис выдает структуры, по этому сохраняется иммутабельность данных.
Если есть к примеру необходимость при переходе на экран всегда показывать актуальные данные, значит есть смысл каждый раз при показе экрана эти данные просить у сервиса из «кэшируемых». Это накладывает свои ограничения, но явно показывает принцип работы этого экрана. К тому же пропадает расхождение между хранимыми и показываемыми данными (если разумеется их показывают «как есть»).
Опять же, если полученные данные из сервиса изменить, это будет только локальным изменением.
1) По мне абсолютно нормальная практика когда ViewModel имеет переменные (уже как минимум если используем биндинги), хотя бы на уровне PropertyType. Потому что это ViewModel и это его задача прямая взять на себя работу с данными для экрана. Либо мы говорим о разных понятиях под ViewModel.
Взаимодействие Controller — ViewModel будет работать как раз на сигналах, ViewModel будет иметь сигналы, в которые будет сообщать о ситуациях нужных для контроллера. Либо создавать и отдавать их обратно контроллеру на действия, в зависимости от ситуации.
Конечно, можно разнести все такие сигналы в PropertyType, но жизнь от этого проще не станет.
2) О создании, кто что создает… намного лучше взять DI фреймворк (Swinject к примеру)
3) В чем проблема от использования структур и кордаты? Это ведь совершенно разные вещи и между ними взаимодействие только на уровне DAO должно осуществляться. Более того, используя структуру мы можем забить на подход с использованием линз тк это копируемый тип и оставить поля в структурах как мутабельные.
В общем, если нам позволяется совмещать несколько подходов в одном для более быстрого и удобного достижения нужной цели, то это надо использовать. Наш подход состоит в следующем:
Controller — работа с UI + взаимодействие с ViewModel (подписки на сигналы и получение сигналов для действий)
—— ниже больше никто не работает с UI компонентами и работают только с данными.
ViewModel — подготовка данных для Controller + взаимодействие с Service
Service — инкапсуляция работы, не связанная с экранами на прямую. Прячем сюда всю черную работу попутно убирая возможный повтор действий.
—— Service взаимодействует с различными компонентами системы, в зависимости от ситуации.
p.s. реактив должен облегчать работу, а не заставить отказаться от парадигмы вашего языка. К примеру попытка сделать абсолютно все immutable.
p.p.s. даже в функциональных языках существуют монады.
Только в один скрипт для сабмита в стор надо дописывать фреймворки.
Не поделитесь опытом? В проекте ибо в таргет прикладывается скрипт с путями и какие нужны фреймворки. Возможно я что то делаю не так и как вы пишете можно только в одном скрипте указать фреймворки (как в pod'ах можно было указать вот эти вот на все таргеты, вот этот вот «туда», а этот «туда»)
Также при удалении не нужно ничего пересобирать
ну да, на удаление не надо пересобирать. Но надо убрать из картежфайла запись, из таргета удалить фреймворк, потом найти его в скрипте и убрать путь до него.
Конечно ситуация добавления/удаления не такая и частая, но как то смущает. Особенно когда больше 1 таргета на проекте
минусы рассказать забыли :-)
1) долгое выкачивание и сборка фреймворков когда нужно добавить/удалить что то
2) нужно руками прописывать путь к каждому фреймворку и добавлять фреймворк в проект
2.1) это нужно сделать для каждого таргета
Отлично, как я и написал «Не претендую на уникальность».
В конечном итоге люди узнали/узнают что «можно так», а есть «и вот так уже». Я вот не знал когда делал, думаю я не один такой :-)
1) MVVM не чистый у нас в любом случае (что вызывает зависть у команды winphone :D) = разделение контроллера на presenter + viewmodel
2) применяем сюда SOA
3) роутер этот, вот на этот момент я написал мелкую штуку в 50 строк (долго думал нужно ли писать статью, но решился в сб и сейчас текст статьи на проверке/правке перед релизом, увы я не мастер писать связно там крайне мелкая статья в 1.5 экрана), но она позволяет убрать навигацию в отдельный объект полностью. А использование DI повышает переиспользование и тестирование еще выше
ах да, сториборды, сейчас на моем проекте 6 сторибордов ко всему этому
На недели планировал написание о архитектуре с реактивом.
Используем очень плотно реактив (правда RAC2/RAC4 вместо RxSwift) и уже не один проект успешно живет и развивается. Пропитываем сквозь всю модульную архитектуру и нам это очень хорошо помогает разделять и лучше читать.
Ну и соотвественно за счет разделения отличная тестируемость достигается
при хорошем разделении кода, отладка на RAC не сильно сложнее чем обычный асинхронный код
наши проекты пропитаны реактивом и включение человека на проект не является неподъемной задачей
Если бы Вы ограничили статью только темой «Разбираемся с NSMethodSignature на примере комбинирования stringWithFormat и NSArray» и убрали привязку к target-action
Не поверите, было такое желание вынести центр статьи в отдельную статью с таким названием (и было так в начале кстати). Но потом люди которые читали черновой вариант изъявили желание читать все вместе чтобы не теряться в материале
Да, ломается 2х строчное решение
Но это все равно меньше пары классов и статьи на пару А4. А по сути всего один метод у UIButton
Это и есть тот самый обычный подход о котором я писал что в других либах, только там это делается сразу на уровень выше для остальных контролов чтобы было
И потом такие же для инициализаторов на барбатоны, на таймеры, на жесты и еще на много чего и на самом деле если это собрать, то получится не мало категорий
Здесь решение максимально общее и по факту совсем не большое если сравнивать от эффекта добавления множества категорий
1) target-action ни есть задача о performSelector:withObject:
Вы правы. Но суммарный результат, что решение применимо для любого действия где дергается через селектор вызов, я не смог подобрать лучшее определение
приведите пример использования invoke, когда блок принимает аргументы
к примеру для вызова через performSelector:withObject:
ну или когда по нажатию на кнопку надо получить кнопку и евент
так же интересно, какое неверное представление я дал о блоках?
p.s. а я и не думал обижаться :-) это про "не злой"
Вообще, по-моему ещё в 2018 уже было или даже раньше. Точно знаю что был натив тк при мне оно было. С годами могу чуть ошибиться, но когда в 2019 уходил оно уже точно в доступе было
Оно? Не могу сам поставить тк до зимы в лучшем случае винды под рукой не будет
https://apps.microsoft.com/store/detail/яндексмузыка/9NBLGGH0CB6D?hl=ru-ru&gl=ru
На удивление, вот как раз там не электрон. Отдельно win phone разраб занимался под винду попутно с винфоном
а где связь между
и
От того что будет ясен мой портрет это как то изменит рейтинг? Или мой голос не будет засчитан если я поставлю не тот пол или возраст?
p.s. выбор лейблов это просто нечто, мне уже не интересно кого выбрали, а интересно увидеть цифры сколько отвалилось людей на этом этапе
Симуляция нужна только при дебаге, убедится что все работает как надо.
Про погрешность я уже писал, зато вспомнил благодаря комментарию о "авиарежиме", отсутствии симкарты и блокировке GPS, что дописал в "интересные моменты".
Да, большое спасибо, недоглядел. Использование в таком виде allowDeferredLocationUpdates в принципе бесполезно было, по статье и коду убрал, текст дополнил.
Код писался с максимально простотой, по этому отсутствует обработка ошибок в принципе didFailWithError / didFinishDeferredUpdatesWithError (CLError.h).
Про то что allowDeferredLocationUpdates вызывается до didUpdateLocations:
Соблюдено, CLLocationManager уже запущен. didUpdateLocations это не старт менеджера, первый вызов метода может быть и спустя пару минут, что наблюдал на практике.
Другое дело, что обычно allowDeferredLocationUpdates вызывается из didUpdateLocations, потому что в документации дальше следует:
p.s. большое спасибо за комментарий, попутно вспомнил и поправил в статье, что я забыл о нюансах allowDeferredLocationUpdates и выпилил использование из примера ибо влиять в том использовании не должно было.
p.p.s. статью писал почти через 9 месяцев "не работы" с геолокацией, немного подзабыть успел, надеюсь никому не навредил "бесполезным" куском кода.
Про скорость вот тут можно глянуть.
Про точки и промежутки не понял вопроса, метод вызывается когда новые данные появились (обычно в массиве 1 элемент, но к примеру при использовании `defer` в массиве все точки что накопились)
Когда весь проект на swift, много чистых swift элементов, то тут и начинается проявляться проблема «оберток» о которой я упомянул, но похоже забыл написать в статье. Это относится к различию между Any и AnyClass когда надо в prepareForSegue передавать данные.
К тому же если принять соглашение к именованию контроллеров в сториборде как сам класс, то можно используя небольшую модификацию вместо идентификатора передавать класс и получать в замыкание уже приведенный экземпляр класса (не писать постоянно as! в замыкании)
первым делом написан был скрипт на башике, который делал файл с тем что компилится больше 1мс (потом увеличил до 50) и выводит суммарное время сборки.
Результат ~ 32'000ms
Прошерстил 2 функции (flatMap цепочка одна фунция и убрал lazy в другом месте) и уже 20'000ms
Еще 2 функции перебрал и уже 18сек компиляция
Собственно всего то разнес во временные переменные результаты
Кстати, если все перевести в такие переменные, сложно сопоставлять будет действия когда придет новый человек. А вот если сервисы выдают сигналы и на них подписываются из Presentation (ViewModel к примеру и потом выдает результат по необходимости в Controller на обновления) то сложного ничего нет, потому что разделяются обязанности: сервис сконфигурировал, ViewModel подготовил данные и обновился Controller
Биндинга между моделью и вьюмоделью не делаем, сервис выдает структуры, по этому сохраняется иммутабельность данных.
Если есть к примеру необходимость при переходе на экран всегда показывать актуальные данные, значит есть смысл каждый раз при показе экрана эти данные просить у сервиса из «кэшируемых». Это накладывает свои ограничения, но явно показывает принцип работы этого экрана. К тому же пропадает расхождение между хранимыми и показываемыми данными (если разумеется их показывают «как есть»).
Опять же, если полученные данные из сервиса изменить, это будет только локальным изменением.
1) По мне абсолютно нормальная практика когда ViewModel имеет переменные (уже как минимум если используем биндинги), хотя бы на уровне PropertyType. Потому что это ViewModel и это его задача прямая взять на себя работу с данными для экрана. Либо мы говорим о разных понятиях под ViewModel.
Взаимодействие Controller — ViewModel будет работать как раз на сигналах, ViewModel будет иметь сигналы, в которые будет сообщать о ситуациях нужных для контроллера. Либо создавать и отдавать их обратно контроллеру на действия, в зависимости от ситуации.
Конечно, можно разнести все такие сигналы в PropertyType, но жизнь от этого проще не станет.
2) О создании, кто что создает… намного лучше взять DI фреймворк (Swinject к примеру)
3) В чем проблема от использования структур и кордаты? Это ведь совершенно разные вещи и между ними взаимодействие только на уровне DAO должно осуществляться. Более того, используя структуру мы можем забить на подход с использованием линз тк это копируемый тип и оставить поля в структурах как мутабельные.
В общем, если нам позволяется совмещать несколько подходов в одном для более быстрого и удобного достижения нужной цели, то это надо использовать. Наш подход состоит в следующем:
Controller — работа с UI + взаимодействие с ViewModel (подписки на сигналы и получение сигналов для действий)
—— ниже больше никто не работает с UI компонентами и работают только с данными.
ViewModel — подготовка данных для Controller + взаимодействие с Service
Service — инкапсуляция работы, не связанная с экранами на прямую. Прячем сюда всю черную работу попутно убирая возможный повтор действий.
—— Service взаимодействует с различными компонентами системы, в зависимости от ситуации.
p.s. реактив должен облегчать работу, а не заставить отказаться от парадигмы вашего языка. К примеру попытка сделать абсолютно все immutable.
p.p.s. даже в функциональных языках существуют монады.
Не поделитесь опытом? В проекте ибо в таргет прикладывается скрипт с путями и какие нужны фреймворки. Возможно я что то делаю не так и как вы пишете можно только в одном скрипте указать фреймворки (как в pod'ах можно было указать вот эти вот на все таргеты, вот этот вот «туда», а этот «туда»)
ну да, на удаление не надо пересобирать. Но надо убрать из картежфайла запись, из таргета удалить фреймворк, потом найти его в скрипте и убрать путь до него.
Конечно ситуация добавления/удаления не такая и частая, но как то смущает. Особенно когда больше 1 таргета на проекте
1) долгое выкачивание и сборка фреймворков когда нужно добавить/удалить что то
2) нужно руками прописывать путь к каждому фреймворку и добавлять фреймворк в проект
2.1) это нужно сделать для каждого таргета
В конечном итоге люди узнали/узнают что «можно так», а есть «и вот так уже». Я вот не знал когда делал, думаю я не один такой :-)
2) применяем сюда SOA
3) роутер этот, вот на этот момент я написал мелкую штуку в 50 строк (долго думал нужно ли писать статью, но решился в сб и сейчас текст статьи на проверке/правке перед релизом, увы я не мастер писать связно там крайне мелкая статья в 1.5 экрана), но она позволяет убрать навигацию в отдельный объект полностью. А использование DI повышает переиспользование и тестирование еще выше
ах да, сториборды, сейчас на моем проекте 6 сторибордов ко всему этому
Используем очень плотно реактив (правда RAC2/RAC4 вместо RxSwift) и уже не один проект успешно живет и развивается. Пропитываем сквозь всю модульную архитектуру и нам это очень хорошо помогает разделять и лучше читать.
Ну и соотвественно за счет разделения отличная тестируемость достигается
наши проекты пропитаны реактивом и включение человека на проект не является неподъемной задачей
Не поверите, было такое желание вынести центр статьи в отдельную статью с таким названием (и было так в начале кстати). Но потом люди которые читали черновой вариант изъявили желание читать все вместе чтобы не теряться в материале
Это и есть тот самый обычный подход о котором я писал что в других либах, только там это делается сразу на уровень выше для остальных контролов чтобы было
И потом такие же для инициализаторов на барбатоны, на таймеры, на жесты и еще на много чего и на самом деле если это собрать, то получится не мало категорий
Здесь решение максимально общее и по факту совсем не большое если сравнивать от эффекта добавления множества категорий
Вы правы. Но суммарный результат, что решение применимо для любого действия где дергается через селектор вызов, я не смог подобрать лучшее определение
к примеру для вызова через performSelector:withObject:
ну или когда по нажатию на кнопку надо получить кнопку и евент
так же интересно, какое неверное представление я дал о блоках?
p.s. а я и не думал обижаться :-) это про "не злой"