[Из песочницы] Как упростить жизнь iOS разработчику
Наверное, каждый разработчик, когда начинает осваивать новую технологию, хочет опробовать все самостоятельно, реализовать все с самого низкого уровня, чтобы потом наслаждаться результатом своей работы. Однако с накоплением опыта многие задачи становятся достаточно скучными и хочется избавить себя от этой нужной, но неинтересной рутины. В этой статье я хочу поделиться тем, какие способы и средства помогут упростить жизнь разработчику и сэкономить нервы.Настройка проекта, среды разработки, подключение библиотек, сниппетыЭто один из первых и самых легких, но все-таки существенных действий, однако про это уже написано много статей, таких как эта, эта, эта и вряд ли есть разработчик, который этого не знает, поэтому на этом останавливаться не будем. Также, для Xcode написано довольно много полезных плагинов, обзорную статью по которым можно почитать тут.Свой репозиторий CocoaPods Помимо подключения своих любимых или нужных для этого проекта библиотек через CocoaPods, можно добавить свой репозиторий с самыми частыми «функциями-помощниками». Например, кому не надоедает писать код следующего вида: [self.subviews makeObjectsPerformSelector:@selector (removeFromSuperview)]; или NSData *data = [responseString dataUsingEncoding: NSUTF8StringEncoding]; return [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: nil]; Чтобы избавить себя от этого, я использую на GitHub репозиторий с полезными категориями, которые сильно сократят написание кода. Воспользовавшись им, это все можно переписать следующим образом: [self removeAllSubviews]; return responseString.JSON; Локализация приложения Практически всегда требуется сделать не менее двух-трех локализаций проекта. В Xcode есть для этого свои средства, и нужно отдать должное разработчикам Apple за то, что они их улучшают, но все-таки это не самый удобный способ, особенно если приложение уже в AppStore и нужно выпустить обновление — проблем хватает как с Base Internationalization, так и с Localizable.Strings. Те, кто с этим уже сталкивался, знает, что Xcode не умеет дописывать или обновлять значения в локализованных *.strings файлах для Storyboard, а также утилита genstrings ожидает на вход только новые добавленные строки, разве что мы не захотим перегенерировать все вхождения заново.Начнем с Localizable.Strings. Я выделяю отдельный h-файл для NSLocalizedString, например StringConstants.h, в котором через #define определены локализованные строки. С помощью такого подхода можно убить сразу двух зайцев:
Собрать общие фразы и слова, такие, как «Отмена», «Выйти», «Неверный логин или пароль» и др., которые с большой вероятностью будут присутствовать в любом проекте, так что его можно будет таскать с собой с уже готовыми строками Переиспользовать уже существующие строки внутри проекта, не набирая каждый раз длинный и неудобный макрос NSLocalizedString Так, показ стандартного UIAlertView с сообщением об ошибке будет выглядеть следующим образом: [[[UIAlertView alloc] initWithTitle: kErrorString message: kInvalidLoginOrPasswordString delegate: nil cancelButtonTitle:@«OK» otherButtonTitles: nil] show]; Что касается генерации локализованных файлов, то для этого я использую второй h-файл, NewStringConstants.h, в который добавляю те вхождения, которые необходимо локализовать, после чего удаляю их. Непосредственно в Localizable.Strings новые вхождения добавляет скрипт в Build Phases: cd ${PROJECT_DIR}/MyProject genstrings -a -o Base.lproj NewStringConstants.h genstrings -a -o ru.lproj NewStringConstants.h genstrings -a -o pt-PT.lproj NewStringConstants.h genstrings -a -o es.lproj NewStringConstants.h Все, что остается сделать после этого — написать локальные значения строк в Localizable.Strings-файлах.Со Storyboard задача решается также через скрипт, который детально рассматривается в этой статье. Здесь хочу кратко упомянуть, что суть работы скрипта заключается в том, что он извлекает строки из Storyboard с помощью утилиты ibtool, и при вызове проверяется, не произошло ли каких изменений. При наличии последних делается экспорт локализованных строк, после чего локализованные файлы мержатся. Опять-таки остается подправить локализованные файлы. Также хочу упомянуть про инструмент AppleGlot, про который говорится в приведенной выше статье, однако он использует другой подход в итеративном обновлении локализации. Выбор конкретного инструмента остается за разработчиком в зависимости от его предпочтений.
Тестирование приложения
Здесь речь пойдет о ручном тестировании приложения в условиях ограниченного количества устройств. Как бы много кода не было покрыто юнит-тестами, нельзя исключать ручное тестирование. В основном этим занимается сам разработчик во время создания приложения, но когда оно готово, необходимо передать приложение обычному пользователю, у которого не «замылен» глаз и который будет использовать приложение как непосвященный во все тонкости работы среднестатистический пользователь. Хорошо, если в наличии имеется весь набор устройств со всеми поддерживаемыми операционными системами, однако в основном это не так. Даже если есть вся линейка устройств, то, как правило, разнообразием операционных систем они не отличаются, что в основном, конечно, и не нужно, но проверить не помешает. На помощь придет симулятор iOS, который можно настроить путем выбора нужного элемента из выпадающего меню. Однако, без дополнительных действий тестировщику придется передавать исходные коды, что не всегда приемлемо. Далее я опишу, как можно передать собранное приложение для тестирования на iOS симуляторе и какое нужно установить для этого дополнительное ПО.Установка sim_launcher и ios-sim
gem install sim_launcher
brew install ios-sim
sim_launcher позволяет запускать iOS приложения в симуляторе через HTTP GET запросы. Это удобно тем, что всю организационную работу для тестирования можно организовать в браузере, не заставляя пользователя запоминать команды терминала. ios-sim представляет из себя некую обертку над командами терминала, упрощая работу с симулятором. Похоже, что sim_launcher не обновляется уже некоторое время, поэтому с последней версией ios-sim он не совместим. Необходимо исправить следующие функции в файле simulator.rb, находящийся в папке установки sim_launcher: Исправления simulator.rb
def start_simulator (sdk_version, device_family)
sdk_version ||= SdkDetector.new (self).latest_sdk_version
run_synchronous_command (: start, '--devicetypeid', sdk_version, '--exit')
end
def launch_ios_app (app_path, sdk_version, device_family, app_args = nil)
if problem = SimLauncher.check_app_path (app_path)
bangs = '!'*80
raise »\n#{bangs}\nENCOUNTERED A PROBLEM WITH THE SPECIFIED APP PATH:\n\n#{problem}\n#{bangs}»
end
sdk_version ||= SdkDetector.new (self).latest_sdk_version
args = [»--args»] + app_args.flatten if app_args
run_synchronous_command (: launch, app_path, '--devicetypeid', sdk_version, '--exit', *args)
end
Запуск билда на симуляторе
sim_launcher
Эта команда поднимает веб сервис на 8881 порту. Указав вместо полный путь к .app-файлу, необходимо перейти в браузере по адресу http://localhost:8881/launch_iphone_app? sdk=com.apple.CoreSimulator.SimDeviceType.iPhone-6,%208.1&app_path=