- iOS-разработка: способы быстрого старта
- Путь от Apple
- Xcode
- Swift 4
- «Гибридное», «не совсем нативное» приложение
- Ionic
- PhoneGap / Cordova
- Xamarin
- React Native
- Веб, чистый веб
- Как собрать собственный фреймворк для iOS
- Про динамические фреймворки iOS8
- Про сборку SDK
- Про зависимости
- Про ресурсы
- Про версионирование
- Вместо заключения
iOS-разработка: способы быстрого старта
Когда мы задумываемся о разработке под iOS, чаще всего в голове возникает пятизначная сумма входного порога: как минимум нужно iOS-устройство на последней версии ОС и Mac. Если вы уже пишете под iOS, вам наверняка известны альтернативные варианты, а если нет — посмотрите, вдруг пригодится? Приведенный ниже обзорный пост — как раз на этот случай. Под катом вы найдете довольно простую информацию, так что если хотите хардкорчика, вам не сюда!
Итак, у нас в руках iOS-устройство, в голове — идея приложения, в сердце — желание поскорее овладеть новыми знаниями. Перед нами три пути, прямо как у былинного богатыря:
- Берем Mac (точнее, нам нужна OS X), берем Xcode с iOS SDK, берем Objective-C или Swift, делаем проект, и на выходе получаем самое настоящее, «нативное», iOS-овское приложение, которое даже можно со спокойной душой засабмитить в App Store, и радоваться
показу баннеровтому, что наша небольшая разработка приносит людям радость. - Берем хоть Mac, хоть Windows-машину, выбираем фреймворк, позволяющий писать мобильные приложения на более знакомых многим языках (JavaSctipt, C#). Заботу о том, как наш код выполнится на устройстве, возьмет на себя фреймворк: для обеспечения выполнения с нашим кодом будет слинкован механизм исполнения кода (runtime), в задачи которого, среди прочего, входит трансляция вызовов используемого языка программирования в API мобильной платформы. Плюс подхода состоит в определенной независимости от конкретной мобильной платформы (с которой нас связывает только сам runtime), минус же — в меньшей, чем у «родного» приложения, скорости работы.
- Берем
Блокнотлюбой редактор текстовых файлов, ваяем веб-страницу, должным образом ее обустраиваем, и на выходе получаем веб-приложение, которое, по сути, будет запускаться в полноэкранном окне браузера (как самое настоящее приложение на платформе — без адресной строки браузера), но работать будет, конечно, со скоростью и отзывчивостью обычной веб-страницы. В первую очередь это будет видно при отсутствии нормального интернет-соединения, однако, согласитесь, даже такой вариант иногда удобен. Веб-приложение, кстати, имеет тот плюс, что для доступа пользователей к нему страницу не требуется отправлять в App Store, достаточно дать людям ее URL и предложить добавить себе «на домашний экран».
Путь от Apple
Путь настоящего джедая тру iOS-разработчика лежит в плоскости следования идеям Apple. Свежий SDK, свежая же версия Xcode, документация от Apple по технологиям Apple, форумы разработчиков на технологиях Apple – если вдуматься, а что ещё нужно для создания отличного приложения, кроме толики времени? Польза очевидна: разработка идет самым близким к платформе и к идеологии Apple образом, с использованием всех новинок, предлагаемых Apple в текущем (и будущих) iOS API, так что постоянное изучение нового приносят больше хорошего, чем плохого.
Новинки Apple озвучивает регулярно. На последней конференции для разработчиков WWDC 2017 были показан новый SDK и новая версия среды для разработке Xcode. Список изменений довольно обширен (тем более в преддверии выхода iOS 11):
Xcode
Текстовый редактор в Xcode переписали на Swift, сделав его надёжнее и быстрее. Можно ли это почувствовать? Да! Подсветка синтаксиса работает (почти) моментально, открытие и навигация по файлу теперь без заметных задержек, а сообщения об ошибках больше не перекрывают исходный код. В beta все выглядит очень приятно, посмотрим, что нас ждет в релизе!
В Xcode появилась поддержка Markdown. Разметку можно использовать при документировании кода, и функциональность эта, на первый взгляд, косметическая, довольно заметно облегчает чтение кода, особенно чужого:
(Источник)
Редактор, кстати, научился подсвечивать блоки кода, удобно при изучении большого объёма кода.
(Источник)
Ещё одной важной фичей Xcode 9 стал рефакторинг кода на Swift, Objective-C, Objective-C++, C. Рефакторинг позволяет переименовывать классы, переменные, а также дробить методы на менее крупные.
(Источник)
Из менее выделяющихся, но тем не менее полезных фич, можно назвать:
- Новую систему сборки (кстати, написанную на Swift);
- Поддержку GitHub;
- UI debugger стал показывать UIViewController;
- Добавили больше проверок (например, main thread API checker и undefined behavior tracking);
- Параллельный запуск тестов на разных устройствах и симуляторах, UI-тесты нескольких приложений;
- «Беспроводную» отладку на нескольких устройствах для проверки приложений под iPad и iPhone.
Swift 4
Это изменение стоит особняком. Все, кто уже пережил чувство «в Swift 2 было, в Swift 3 пропало?!», могут ощутить дежавю, но сейчас ожидаются изменения, скорее, в лучшую сторону (впрочем, замечу вполголоса, когда это было не так, по мысли авторов-то?)
- Приложения, написанные на Swift 4, станут меньше в размерах.
- Swift 4 получит встроенную поддержку кодирования/декодирования в/из JSON. До Swift 4 приходилось много писать много кода самому, либо использовать сторонние кодогенераторы. Сейчас этот код генерирует компилятор. Отдельное спасибо!
- Возврат к удобной модели работы со строками, которая была реализована в Swift 2 и убрана в Swift 3. Вместе с этим изменением строки станут лучше поддерживать Unicode («чтобы ваши любимые приложения корректно показывали все ваши emoji»), а работа с ними ускорится.
- Проекты, в которых используется и Swift, и Objective-C, будут собираться на 40% быстрее за счёт улучшений в Xcode 9 и его системы сборки.
- Apple (как обычно) обещает простую миграцию на Swift 4, и одновременную поддержку разных кодовых баз (3.2 и 4.0).
«Гибридное», «не совсем нативное» приложение
Уточню: термин, вынесенный в заголовок, даже по сути своей не очень верен. Приложения, которые мы получим в результате, самые что ни на есть нативные в смысле того, что они исполняются на той же iOS, на том же железе, что и любое другое ПО для iOS, просто сам процесс разработки позволяет использовать не только предложенные Apple технологии и языки программирования. Если человек умеет писать, скажем, на JavaScript, и не хочет разбираться в Swift, то Apple ему ничем не поможет (кроме, конечно, хорошего учебника по Swift), а вот вариант написать, условно говоря, приложение на JavaScript, а потом запустить его на iOS, как если бы оно было написано в Xcode (получив, таким образом, некий «гибридный» вариант) существует, и вполне востребован.
Ionic
Ionic – один из самых известных фреймворков для кросс-платформенной разработки. Он построен на базе Apache Cordova, что обеспечивает доступ к различным функциям устройства, таким как геолокация, push-уведомления, камера и прочим, и позволяет разработчикам создавать приложения для iOS и Android с веб-технологиями, такими как HTML, CSS и JavaScript.
В дополнение к фреймворку, Ionic может похвастаться целой экосистемой, облегчающей разработчикам-новичкам процесс изучения и вхождения. Ionic Cloud предоставляет разработчикам различные инструменты для управления, развертывания и масштабирования приложений на Ionic. Ionic Creator представляет собой визуальный редактор, который позволяет разработчикам быстро прототипировать и создавать мобильные приложения методом drag&drop. Наконец, существует Ionic View — бесплатное приложение для iOS и Android, которое позволяет разработчикам легко делиться своим Ionic-приложением с пользователями, тестерами и клиентами без необходимости развертывать приложение в магазине приложений конкретной мобильной платформы. Разработчики просто отправляют пользователям приглашение из приложения Ionic View, и как только оно принято, пользователь может загрузить и запустить конкретное приложение в своей копии Ionic View — так, как если бы приложение было установлено на его телефоне из магазина приложений.
Увы, есть и «ложка дегтя». Приложения, написанные с использованием Ionic, используют WebView, в результате мы получаем самое натуральное веб-приложение, со своей обычной (обычно не самой впечатляющей) скоростью работы. За счет этого трудно считать его подходящим для создания тяжелых приложений, таких, как игры, либо программы с интенсивным использованием графики. Разработка с Ionic требует хороших знаний Angular, по крайней мере при желании «выжать» из фреймворка как можно больше.
PhoneGap / Cordova
PhoneGap исходно был создан компанией Nitobi. В 2011 году, Adobe приобретает Nitobi и бренд PhoneGap. Adobe затем передает одну из версий PhoneGap (назвав её Cordova), в Apache Foundation, оставив себе бренд PhoneGap и его как продукт. В результате Cordova можно рассматривать как движок, стоящий под капотом PhoneGap (а также некоторе другие гибридные фреймворки). PhoneGap, в свою очередь, добавляет к возможностям Cordova свои, дополнительные, функции.
PhoneGap во многих отношениях очень похож на Ionic. Он так же дает разработчикам возможность создавать кросс-платформенные приложения при помощи веб-технологий, и так же построен на базе Apache Codova. Однако PhoneGap не привязан к какому-то определенному Javascript-фреймворку, поэтому разработчики имеют бОльший выбор, на чем и как они будут создавать свои приложения. У PhoneGap имеется десктопное приложение, мобильное приложение, и облачный сервис под названием PhoneGap Build, который позволяет собирать и деплоить приложение.
Увы, подобно Ionic, PhoneGap использует WebView (который в iOS работает довольно медленно), так что со скоростью у приложений, созданных на базе этого фреймворка, дела не всегда обстоят блестяще.
Xamarin
Основанная в 2011 году компания Xamarin, выпускающая семейство продуктов Xamarin через пять лет своего существования была купена компанией Microsoft. Сегодня продукты Xamarin представляют на рынке очень интересный подход к разработке кросс-платформенных мобильных приложений: приложения пишутся на C#, затем Xamarin компилирует его в нативное приложение для iOS, либо для Android, при этом в качестве базовой технологии Xamarin использует Mono, чем кросс-платформенность и обеспечивается. Разработчики Xamarin говорят, что полученные на выходе приложения используют нативное API платформы, для которой приложение компилируется, так что поведение полученного приложения никак не отличается от поведения любого другого приложения на этой же платформе. Разработку, кстати, можно вести при помощи Visual Studio (что совсем неудивительно).
Несмотря на то, что большая часть кода проекта может быть без изменений использована на каждой из поддерживаемых мобильных платформ, тем не менее, некоторые фрагменты потребуется писать специально для версии приложения под iOS и под Android.
React Native
Проект React Native появился на свет в Facebook, и построен на основе React. Наше JS-приложение крутится на встроенном в iOS движке: на нем выполняется код и производятся все манипуляции с нативными виджетами ОС. React Native сопоставим с Xamarin, при этом приложения, созданные с помощью React Native, очень похожи на нативные приложения iOS и Android (потому что они собственно, оперируют нативными UI-элементами).
Синтаксис React довольно прост, что облегчает изучение фреймворка, а Стандартная библиотека UI-компонентов в поставке React Native содержит много полезных компонентов, однако самым большим отличием React Native от других JavaScript-фреймворков называют возможность использования кода на на Objective-C и Swift (чаще для для улучшения производительности или более тонкого взаимодействия с мобильной платформой). На практике это означает, что разработчики могут использовать существующие собственные библиотеки в своих приложениях React Native.
Веб, чистый веб
Часто недооцениваемая возможность использовать веб-страницу как отдельное приложение тем не менее к нашим услугам: если нет особых проблем со связью, а приложение обладает несложной функциональностью (вывод таблицы данных, или вывод постоянно обновляемого списка), то нет причин не воспользоваться старым добрым веб-просмотром информации с сервера.
Разница между открытием той же страницы в браузере будет в оформлении экрана: элементы управления браузера (в т.ч. и адресная строка) будут спрятаны, а содержимое страницы окажется выведенным на весь экран устройства. Из неудобств нас, конечно, ждет довольно долгое время открывания такого «приложения» (что связано со скоростью ответа удаленного веб-сервера), но для ряда применений это, думаю, вовсе не проблема.
Разработка приложений для мобильных платформ имеет свой подвох: поначалу думаешь, что дело не стоит усилий и времени, затем твоим приложением начинают пользоваться люди, причем пользоваться, в буквальном смысле нося его с собой, и вот тут ты понимаешь, что дело оказалось глубже, и затянуло тебя больше, чем ты мог бы себе представить.
Если вы любите мобильную разработку так же, как любим ее мы, рекомендую обратить внимание на следующие доклады Mobius 2017 Moscow (да-да, в ноябре Мобиус едет в Москву, если вы еще не знали):
Источник
Как собрать собственный фреймворк для iOS
Среди задач мобильного разработчика, помимо самой частой (написания, собственно, приложений) периодически появляется и такая, как создание sdk.
Примерами такой задачи может быть создание sdk, использующего REST API какого-либо сервиса (реклама, аналитика, погода), библиотека реализаций алгоритмов, обработка изображений… Список практически неограничен.
Ошибки, допущенные в таком продукте, исправлять гораздо сложнее, чем при разработке приложений. В случае с приложением достаточно обновить его в AppStore, дождаться прохождения модерации и обновления пользователем. В случае же с sdk цепочка прирастает дополнительным шагом — дождаться его обновления разработчиком.
Для некоторых типов задач ситуация может усугубляться ещё и тем, что не все разработчики приложений использующие наш sdk могут быть достаточно квалифицированы. В связи с этим интеграция должна вызывать минимум сложностей. В особенности это касается рекламных sdk и аналитики, так как зачастую они встраиваются гораздо позднее основного этапа создания приложения и не всегда первоначальным разработчиком.
Любой подобный sdk обычно состоит из многих компонент: библиотеки, тестового приложения, документации, плагинов к другим инструментам. В этой статье я расскажу о сборке библиотеки в виде фреймворка, некоторых приёмах и особенностях разработки.
Для начала, небольшая ремарка о решаемой задаче. Наша цель — получить библиотеку в таком формате, который требует минимум усилий и знаний при интеграции, а также не имеет побочных эффектов после неё.
Таким решением может стать, к примеру, CocoaPods, который, в частности, позволяет распространять пакеты с закрытым исходным кодом. Существует достаточно много статей (например здесь или здесь), описывающих, как публиковать свои библиотеки в CocoaPods, и повторяться мы, пожалуй, не будем.
Для нашего sdk, рассчитанного на широкий круг разработчиков, такого способа распространения, очевидно, недостаточно: часть разработчиков не пользуются им принципиально («а вдруг опять github заблокируют?»), часть же не слышали о нем вовсе.
Сфокусируемся на сборке sdk в формате фреймворка. Всё, что понадобится пользователю для интеграции — перетащить его к себе в проект.
Про динамические фреймворки iOS8
The MinimumOSVersion of framework «. » is invalid. The minimum value is iOS 8.0;
ld: embedded dylibs/frameworks are only supported on iOS 8.0 and later
Резюме по динамическим фреймворкам на данный момент такое: использовать и распространять их возможно, но только если минимальная версия iOS SDK начинается с 8.
Про сборку SDK
Попробуем воспользоваться тем же шаблоном динамического фреймворка, который предоставляет Xcode 6, но теперь уже для сборки его статической версии. Оказывается, после некоторых модификаций это вполне возможно. Приступим.
Создадим новый проект, где в качестве типа таргета выберем Cocoa Touch Framework. Имя выбираем любое. Для определённости, наш назовём MySDK.
Добавляем в проект классы нашего sdk. Заголовочные файлы, которые должны быть публично доступны, помечаем как Public и импортируем в umbrella-header, который по умолчанию был создан с проектом. В нашем случае он называется MySDK.h
Далее, заходим в BuildSettings нашего таргета и в секции Linking меняем Mach-O Type на Static Library.
В настройках схемы нашего таргета поменяем конфигурацию запуска на Release. Это действие необходимо для того, чтобы сборка происходила для всех доступных архитектур, а не только для активной.
Разработчик, использующий нашу библиотеку, наверняка захочет запускать код на всех возможных для iOS архитектурах процессоров. И мы должны об этом позаботиться. На данный момент актуальный список архитектур включает 3 для устройств (armv7, armv7s, arm64) и 2 для симуляторов (i386, x86_64). Для этого необходимо собрать так называемую fat binary библиотеку, которая будет включать в себя слои для каждой из поддерживаемых архитектур. Для этого создадим в проекте таргет типа Aggregate. Назовём его MySDKUniversal.
В BuildPhases таргета добавляем фазу Run Script со следующим скриптом:
Здесь мы дважды вызываем сборку нашего фреймворка и собираем получившиеся библиотеки в один fat binary с помощью утилиты lipo. Обратите внимание на последний параметр ARCHS при вызове xcodebuild. Если его не указать, то сборка для девайса будет использовать список архитектур по-умолчанию описанный в переменной ARCHS_STANDARD. Дело в том, что Apple, судя по всему, намеренно исключила из переменной ARCHS_STANDARD armv7s для Xcode6, оставив только armv7, arm64. В целом, в этом нет большой проблемы для разработчика, и в приложении он практически всегда может исключить armv7s. Приложение без особых проблем, хотя, вероятно, и с меньшей оптимизацией, будет работать на процессорах A6, A6X. Но, разрабатывая sdk, не стоит принимать такое решение за разработчика. Гораздо проще перечислить список архитектур явно.
Про зависимости
Редко какой код сможет обойтись без сторонних зависимостей. Например, библиотеки работы с сетью, различные парсеры, категории к классам системных фреймворков и т.д. В итоге, все эти классы попадают в наш sdk, и разработчик, который его использует, сможет столкнуться с проблемами при сборке своего проекта. Эти проблемы начнутся как только он захочет использовать одну из тех «вшитых» в sdk библиотек. Компилятор выдаст кучу “duplicate symbols” при сборке его приложения. Казалось бы, что в этом плохого: разработчику всего лишь нужно удалить из зависимостей эту библиотеку, так как её классы уже есть в нашем sdk. Загвоздка в том, что он лишается возможности обновлять эту библиотеку и становится зависим от наличия нашего sdk.
Решение, которое, с некоторыми оговорками, можно назвать лучшим из имеющихся, заключается в добавлении префиксов ко всем импортируемым символам используемых библиотек. К процессу сборки нашего фреймворка добавляется ещё шаг. Для этого создадим отдельный таргет проекта, в котором будем собирать статическую библиотеку со всеми зависимостями. Назовём его ext.
Добавляем все наши зависимости в раздел CompileSources списка фаз сборки. Последней фазой добавляем кастомный скрипт. Сам скрипт берём здесь. Не забываем поправить префикс, который будем добавлять к символам из библиотеки, и путь к заголовочному файлу, который будем генерировать. В нашем случае это:
Запускаем сборку нашего таргета `ext`. Получившаяся в результате этого библиотека нам не понадобится. Интерес представляет получившийся заголовочный файл NamespacedDependencies.h. Убедитесь, что он не пустой и содержит макросы, которые подменяют имена символов нашей библиотеки зависимостей. После этого добавьте получившийся заголовочный файл к нашему основному таргету MySDK.
NamespacedDependencies.h должен быть импортирован перед импортом любого из хедеров зависимостей. Наиболее подходящим для этого местом в проекте является PCH файл. Если он ещё не существует в проекте, то необходимо его создать. Не забываем указать путь к нему в настройках таргета.
Теперь при сборке нашего фреймворка все символы из библиотек-зависимостей будут снабжены указанным префиксом. Этот факт можно проверить запустив утилиту nm.
В результате такого трюка наш sdk не будет вызывать конфликтов при использовании тех же зависимостей в конечном проекте, хотя, конечно, и увеличит размер собранного приложения.
Про ресурсы
Помимо, собственно, скомпилированной библиотеки, очень часто появляется необходимость распространять её вместе с ресурсами: такими как изображения, звуки, xib файлы и т.д. И cтруктура фреймворка может содержать в себе папку с ресурсами. Однако, Xcode её попросту игнорирует.
Чтобы иметь возможность добавить ресурсы к себе в проект, нужно распространять вместе с фреймворком либо отдельный бандл с ресурсами, либо символическую ссылку на ресурсы, расположенные внутри самого фреймворка.
Способ 1
Для ресурсов создадим отдельный бандл, который разместим внутри фреймворка.
Все наши ресурсы разместим в нём, а его, в свою очередь, уже внутри фреймворка.
Из-за того, что мы воспользовались шаблоном Bundle для OS X, важно не забыть произвести ещё несколько настроек в таргете бандла.
- установить Base SDK в Latest iOS (по умолчанию Latest OS X)
- удалить секцию Compile Sources из Build Phases
- установить настройку Combine High Resolution Artwork в NO. Иначе ресурсы для разных плотностей экрана будут собираться в один TIFF файл
После этой настройки можно добавить MySDKResources.bundle в секцию Copy Bundle Resources нашего основного таргета MySDK и таргет MySDKResources в Target Dependencies.
Остаётся добавить символическую ссылку на бандл, находящийся внутри фреймворка. Для этого дописываем в скрипт, собирающий наш универсальный фреймворк строчки.
Теперь для использования sdk, помимо фреймворка, в проект также нужно добавить эту символическую ссылку.
Способ 2
Существенным минусом первого способа является то, что наш фреймворк перестаёт быть цельным. А это очень существенно при распространении sdk. Для случаев, когда это применимо, можно воспользоваться таким приёмом, как встраивание ресурсов в код sdk. Такой метод удобен для хранения ресурсов небольшого размера. Например, это могут быть звуки, изображения кнопок, логотипов или текстовые ресурсы. Естественно, список не ограничивается этим набором, ресурсы могут быть абсолютно любые.
Здесь на помощь придёт утилита xxd, у которой есть замечательная опция вывода в формате статического C-массива. Я использую такой дополнительный скрипт генерации ресурсов в Build Phases проекта, который нужно добавить как Run Script перед Compile Sources.
Полученный MySDKResources.h добавляем в проект. После чего ресурсами можно пользоваться, создавая объект NSData, а из него, в свою очередь, и любой другой объект, например, UIImage для изображений.
Про версионирование
При распространении sdk очень удобно для каждого билда иметь уникальный номер версии. Удобство, в основном, заметно при обращении в службу поддержки или при учёте ошибок в багтрекере. Способов формирования номера версии существует множество. Я остановился на таком. Используем формат MAJOR.MINOR.BUILD, где MAJOR.MINOR задаются вручную в зависимости от политики релизов, обратной совместимости версий и т.д. В качестве BUILD берётся количество коммитов в текущей ветке репозитория (релизные сборки происходят всегда из одной ветки). Для автоматизации этого процесса используется небольшой скрипт, который добавляется в BuildPhases таргета до фазы сборки фреймворка. После первой генерации этого файла не забываем добавить его в проект с пометкой public и в наш umbrella-header:
После этого номер версии может быть использован самим sdk. Например, в качестве параметров запроса к API или для вывода в лог.
Вместо заключения
Итак, в этой статье нам удалось охватить некоторые важные аспекты разработки sdk, связанные, в основном, со сборкой. Но на этом круг вопросов, связанных с sdk, далеко не исчерпан. Незатронутыми остались такие интересные вещи, как автоматизация сборки sdk, документирование, автоматизация тестирования sdk, поддержка старых версий iOS, разработка плагинов для таких инструментов как Unity и Adobe Air. Но это — уже тема для отдельной и, может быть, не одной статьи.
Источник