Разработка под iPhone OS. Курс молодого бойца
В последнее время многие начали интересоваться разработкой под iPhone. Причины для этого разные: для кого-то новый рынок, кому-то просто нравится девайс, кто-то услышал сказки о том, что в AppStore полные безделушки могут принести миллионы, банальный интерес, да и суть не в том. Многие до этого занимались программированием в лучшем случае только под Windows, поэтому возникает много вопросов, как писать софт: какой язык, какая среда, как тестировать, как распространять, как получать деньги. И, так как я сам занимаюсь разработкой игрового движка под эту платформу, меня часто просят рассказать что и как. Это я и постараюсь сделать в данной статье, думаю, кому-то пригодится.Итак, о чем мы поговорим:
1) Что нужно для разработки (OS, язык программирования, среда разработки и т.п.)?
2) Подписка разработчика и зачем она нужна.
3) Как собрать простейшее приложение для запуска на своем девайсе и для Ad Hoc?
1) Что нужно для разработки (OS, язык программирования, среда разработки и т.п.)?
Начать стоит с того, что разработка возможна только под Mac OS X. Следовательно, необходим Мак (официально заявлена работа только на Intel, но люди говорят, что получалось и на PPC архитектуре работать), но при желании можно обойтись и хакинтошем (как поставить знает гугл, это выходит за рамки статьи), и, возможно, получится работать даже на VM (сама MacOS вполне нормально бегает, а вот с XCode бывают проблемы). Необходим минимум Leopard 10.5.6 для SDK версии 3.1.3 (текущая доступная для скачивания с сайта Apple) и Snow Leopard 10.6.2 для SDK версии 3.2 (это только для iPad). Впрочем, на торрентах можно найти старые версии SDK, но, насколько я помню, даже версия 2.2.1 требовала леопарда версии 10.5.4.
В принципе, существует возможность собирать приложения под Windows, но тестировать их можно будет только на джейлбрейкнутых устройствах, к тому же без возможности отладки. В любом случае, OS это меньшая из проблем.
Итак, будем считать, что MacOS у нас есть. Для разработки приложений под iPhone OS необходимо скачать и установить iPhone SDK, доступный в соответствующем Dev-центре (http://developer.apple.com/iphone/). Стоит заметить, что инструменты Apple предоставляет бесплатно, платить придется за подписку разработчика. Весит это чудо что-то около 3-х гигабайт и включает в себя IDE (XCode), компилятор (GCC), отладчик (GDB), набор библиотек и заголовков, симулятор iPhone и некоторые дополнительные утилиты (вроде редакторов интерфейса и т.п.). Кстати, используя XCode можно с тем же успехом писать приложения для MacOS.
Для написания программ под iPhone предлагается использовать Objective-C. При этом есть возможность писать так же и на C и на C++ (для этого необходимо изменять расширения файлов с .m на .mm). Правда при этом полностью уйти от Obj-C не удастся, почти весь API рассчитан именно на Obj-C, исключения составляют например OpenGL (хотя для его инициализации придется использовать несколько строк кода на Obj-C), так же полностью доступны стандартные библиотеки C/C++ (так, например, с файловой системой можно работать как средствами SDK на Obj-C, так и используя стандартную библиотеку С для ввода/вывода (fopen(), fgetc(), etc)). Тут уже что кому удобнее и привычнее, но с другой стороны отправка сообщений в Objective-C дороже вызова C-шной функции, поэтому критичный по времени выполнения код лучше наверно писать на C/C++ (а еще лучше на ассемблере или, в некоторых случаях, с использованием VFP (некоторое подобие SSE и т.п. на x86, особенно полезно для игровой математики типа трансформации вектора матрицей в скелетной анимации)). Официальной возможности использования других языков нет (хотя я встречал реализацию Basic генерирующего вместо кода проект для XCode).
О IDE. Apple предлагает нам использовать XCode:

Ничего сверхъестественного, но вполне подходит для работы. Подсветка синтаксиса есть, автоподстановка есть (правда иногда она мешает), менеджер файлов проекта есть, имеется встроенная поддержка систем контроля версий (сам использую svnX, поэтому о встроенной ничего плохого сказать не могу). Для визуального редактирования интерфейса имеются встроенные средства (как для iPhone так и для MacOS). В целом все продумано, удобно. Из недостатков замеченных — часто не видит измененных файлов (изображения, звуки), приходится делать полную очистку проекта и пересобирать полностью. Так же жаловались на лаги подсветки кода. В теории можно воспользоваться и другими IDE, но я этим не интересовался. Для отладки имеем GDB:

Имеются встроенные инструменты профилирования (использование/утечки памяти, нагрузка процессора, статистика OpenGL и т.п.):

Теперь о самом интересном — тестировании приложений.
Во-первых, в SDK имеется симулятор iPhone:

К сожалению, его функционал сильно урезан, например, нет эмуляции акселерометра, функций плеера iPod, проблемы со звуком, жуткая эмуляция мультитача, используется софтварный OpenGL рендер работающий чуть ли не хуже чем на устройстве. С одной стороны, при наличии возможности тестирования и отладки сразу на девайсе симулятор не особо то и нужен, с другой — можно было бы легко записывать видео работы приложения в нормальном качестве и без пальцев поверх экрана (к сожалению, на девайсе можно делать лишь скриншоты одновременным нажатием Home + Power). Так же стоит заметить, что для смулятора приложения компилируются под x86 архитектуру, это необходимо учитывать при работе со сторонними библиотеками.
Что касается тестирования и отладки сразу на девайсе. Для тестирования можно использовать как iPhone так и iPod touch (многие почему-то думают что iPod нельзя). При подключении девайса XCode спросит, хотите ли вы использовать его для разработки. В XCode имеется органайзер (“Window” -> “Organizer”) для управления устройствами, используемыми для разработки:

Используя его, вы можете менять прошивку девайса (для этого их необходимо скачать и установить), управлять provision-профилями (о них позже), управлять установленными приложениями (в том числе получать созданные ими данные), просматривать логи и делать скриншоты. Так же там доступен UDID (Unique Device ID, необходим для создания сертификатов и профилей в iTunes Connect). Главная проблема — для тестирования на устройстве необходимо оформить подписку разработчика ($99 в год), создать и установить сертификаты и provision-профили. Только тогда можно будет установить приложение на устройство. Если был сделан джейлбрейк можно обойтись и без сертификата, так же попадались статьи об обходе подписей, но я не проверял на работоспособность, в конце-концов, $100 в год не такая большая сумма и по большому счету оформление подписки не вызывает проблем если все верно сделать. Подробнее об этом я расскажу ниже.
При запуске приложения из XCode, если оно было собрано под устройство, произойдет автоматическая установка его на девайс и запуск (с отладчиком или без). Отладчик работает полностью, отображает значения переменных, стек вызова функций, функционирует пошаговая отладка и т.п. В общем, практически никаких отличий от разработки и отладки под Windows, например.
2) Подписка разработчика и зачем она нужна.
Теперь о подписке. Как я уже говорил, она необходима для тестирования приложений на девайсе. Кроме того, она дает возможность размешать свои приложения в AppStore (как платные, так и бесплатные) и доступ к форумам разработчиков. Стоит это удовольствие $99 в год. Итак, как оформить подписку.
Для начала необходимо зарегистрироваться в Developers Connection. Тут, я полагаю, ни у кого трудностей не возникнет. Далее залогиниваемся и в iPhone Dev-центре видим справа описание программы и ссылку “Learn More”.

Жмем на ссылку, читаем информацию о том, как нам станет хорошо, когда мы оформим подписку, ищем кнопку «Enroll now» и переходим непосредственно к оформлению. Существует два типа подписок. Первая — для индивидуального разработчика. Вы регистрируете подписку лично на себя и доступ к iTunes Connect имеете только Вы. Это, пожалуй, наиболее простой вариант регистрации, от Вас потребуется только указать свои данные типа адреса, телефона и т.п. Для компаний подойдет второй вариант. Подписка оформляется на компанию, создаются аккаунты администраторов и разработчиков и каждый из них имеет доступ к iTunes Connect (ограниченный их статусом, например, разработчик не может утверждать сертификаты — это задача администраторов компании). Для регистрации могут потребоваться разные бумажки типа разрешение на ведение бизнеса, устава организации и т.п.

После того как Вы заполните все формы, и дело дойдет до оплаты Apple Вас обрадуют сообщением, что в России (Украине и т.д.) невозможно оплатить подписку он-лайн.

Будет предложено скачать PDF с формой, форму необходимо распечатать, заполнить (свои данные, тип подписки, номер регистрации, данные пластиковой карточки (оплатить можно только карточкой, хотя были случаи, когда все-таки соглашались на оплату вайром)) и отправить факсом Apple (не забудьте записать Enrollment ID и Person ID, они потребуются для заполнения формы). Таким образом, понадобится пластиковая карта (MasterCard Standard подойдет точно, VISA не использовал никогда, но знаю человека, который утверждает, что смог оплатить VISA Electron, хотя многие говорили, что ее не принимают). Важно чтобы были разрешены международные транзакции, и стоит вместе с номером карты указать CVV (если есть возможность и боитесь светить его – можно отключить его проверку, хотя многие указывают его, и ни у кого проблем не возникало). Зачастую отсутствующий CVV — главная проблема при регистрации, и, из-за банального незнания как пользоваться карточкой, многие оформляют подписку неделями или даже месяцами. Если все заполнить правильно и Вашу карту примут — весь процесс занимает не более 3-5 дней. Отправлять рекомендуется факсом (лучше настоящим, но можно и через интернет, например в Skype есть расширение для этого, и там даже есть 1 бесплатная тестовая страница), но некоторые кидали и на e-mail, это, во-первых, для уверенности, что они ее получат, а во-вторых, так может оказаться быстрее, т.к. обработкой факсов занимается специальный отдел, не имеющий никакого отношения к iTunes Connect. При получении формы, первым делом проверяют карточку — для этого снимут доллар, который позже вернут. Если транзакция пройдет — снимают стоимость подписки — $99. В любом случае Вы получите сообщение на e-mail о результате. В случае неудачи Вам помогут решить проблему. Если все пройдет успешно — в течение суток с момента получения уведомления об успешной оплате Вы получите письмо со ссылкой для активации подписки. Этим и заканчивается оформление, теперь Вы официальный разработчик под IPhone, и можете выкладывать бесплатные приложения хоть сейчас же (разумеется, сперва они проходят апрув и только потом попадают в AppStore), для платных же необходимо будет заполнить информацию с Вашими банковскими реквизитами, после их проверки будет активирован и контракт для платных приложений.
Вывод денег у нас может стать проблемой (суть в том, что многие банки требуют контракт для подтверждения легальности доходов, а контракта этого на бумаге от Apple разумеется не получить, а товарищи в банках зачастую тупо смотрят на тебя и кричат — «Мы ничего не знаем ни о каком выводе из AppStore! Нет контракта — нет денег!»), но вроде с Альфа-Банком и Райффайзеном проблем не возникает.
На этом о подписке, пожалуй, и все, о создании сертификатов и профилей расскажу далее.
3) Как собрать простейшее приложение для запуска на своем девайсе и для Ad Hoc?
Что ж, iPhone SDK установлен, подписка оформлена, мы готовы начать разработку. Принципы создания, запуска и отладки приложений на девайсе мы рассмотрим на простейшем примере (качать тут). Но сперва подготовительный этап — создание сертификатов и provision-профилей.
Начем с создания запроса сертификата. Запускаем в MacOS Key Chain (Связка ключей), в меню выбираем «Ассистент сертификации» -> «Запросить сертификат у бюро сертификации» и видим такое окошко:

Вписываем свой e-mail и имя (обязательно так же как указывали при регистрации подписки), выбираем «Сохранить на диске» и «Самостоятельно установить информацию о паре ключей» и жмем «Продолжить». Шифрование оставляем без изменения (RSA 2048 бит) и жмем «Продолжить», запрос будет создан и сохранен на диске.
Далее заходим в Dev-центр, в меню справа имеется пункт «iPhone Provisioning Portal», открываем. Данный портал позволяет Вам управлять Вашими сертификатами, устройствами и т.д. В меню выбираем пункт «Certificates» и видим вот это:

Имеется 2 закладки для 2-х типов сертификатов — для разработки и тестирования на девайсах и для дистрибуции. Нам необходимо создать оба. Выбираем файл с запросом сертификата и жмеим «Submit». После этого необходимо подтверждение сертификата администратором компании (если Вы регистрировались как частное лицо — это Вы сами). После подтверждения сертификаты доступны для скачивания. Их необходимо скачать и установить в Связку ключей на MacOS.

Без этих сертификатов Вы не сможете подписывать свои приложения, и, следовательно, распространять их или тестировать.
Мы имеем сертификаты и можем подписывать приложения, но этого не достаточно, еще необходимы provision-профили. Для начала необходимо добавить идентификаторы своих девайсов в iPhone Provisioning Portal. для этого жмем в меню «Devices» и видим вот такое окно со списком:

Apple установила ограничение на добавление девайсов — 100 штук в год. Печально то, что при удалении добавленного девайса счетчик не увеличивается обратно. Жмем кнопку «Add devices» и попадаем сюда:

Тут необходимо ввести имя для устройства и его UDID. За раз можно добавлять несколько устройств. Когда все необходимые данные указаны, жмем «Submit» и устройства окажутся в списке.
Далее, каждое приложение имеет свой идентификатор типа «com.yoursite.appname», они создаются в разделе «App IDs»:

Необходимо указать название для идентификатора (оно ни на что не влияет) и собственно сам идентификатор (обычно это доменное имя, записанное в обратном порядке). Причем есть возможность использовать нечто вроде «com.yoursite.*», тогда этот идентификатор будет подходить для любого Вашего приложения, но для таких универсалов не доступны In App Purchases и Push Notifications.
Теперь все готово для создания provision-профилей. Открываем раздел «Provisioning». Профили, как и сертификаты, делятся на 2 типа: для разработки и дистрибуции. В свою очередь профили для дистрибуции бывают так же 2-х типов: для размещения в AppStore и для Ad Hoc. Ad Hoc дает возможность устанавливать приложения в обход AppStore простым перетаскиванием в iTunes. Это полезно, например, для бета-тестирования, Вы можете добавить UDID девайсов Ваших друзей и коллег и давать им Ad Hoc сборки для запуска.
Итак, создание профиля для разработки:

Вводим имя профиля, выбираем сертификаты, для которых он действителен, выбираем нужный идентификатор приложения и устройства на которых он будет работать.
Процесс создания профиля для дистрибуции практически ничем не отличается:

Разница только в том, что можно выбрать тип дистрибуции, и для AppStore нет необходимости указывать устройства.
После создания профилей необходимо скачать их и установить на устройство через Органайзер. Теперь можно собирать приложения для запуска и тестирования.
Открываем наш тестовый проект, Для начала необходимо внести небольшие изменения в свойства проекта связанные с подписью. Раскрываем группу “Targets” выбираем единственную цель и жмем кнопку Info (либо просто двойной щелчок). В открывшемся окне выбираем закладку «Properties» и в поле «Identifier» пишем необходимый идентификатор приложения, подходящий под имеющиеся provision-профили.

Потом откроем вкладку «Build» ищем там группу «Code Signing» и проверяем, чтобы там стоял правильный идентификатор. Если в выпадающем меню Вы не можете выбрать ни один пункт — проблема либо с сертификатами, либо с provision-профилями.

После этих изменений приложение должно успешно собираться и запускаться на девайсе.
Теперь рассмотрим код и структуру приложения.
Программа, как обычно, имеет точку входа:
- int main(int argc, char * argv[])
- {
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- int returnValue = UIApplicationMain(argc, argv, nil, nil);
- [pool release];
- return returnValue;
- }
В принципе, менять ее не нужно, тут происходит создание пула для сборщика мусора Objective-C и запуск самого приложения. Функция UIApplicationMain() создает делегат приложения и запускает цикл обработки событий. Данные об делегате приложения, связанном с ним окне и элементах управления на нем берутся из специального XML файла генерируемого редактором интерфейса. Программисту остается написать обработку событий. Сам делегат объявлен в заголовке «HabraSampleAppDelegate.h», его реализация находится в «HabraSampleAppDelegate.m». Данный класс примечателен лишь тем, что должен реализовывать протокол UIApplicationDelegate. Реализация его тоже простая и заключается в запуске/остановке отрисовки по различным событиям (типа завершения загрузки приложения, входящему звонку, закрытию приложения).
Чуть больший интерес представляет класс EAGLView, отвечающий за отрисовку средствами OpenGL ES 1.1. При инициализации настраивается слой для рисования:
- CAEAGLLayer * eaglLayer = (CAEAGLLayer*)self.layer;
- eaglLayer.opaque = TRUE;
- eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool: FALSE],
- kEAGLDrawablePropertyRetainedBacking,
- kEAGLColorFormatRGBA8,
- kEAGLDrawablePropertyColorFormat, nil];
Создается и устанавливается активным OpenGL контекст:
- context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
- if(!context || ![EAGLContext setCurrentContext: context])
- {
- [self release];
- return nil;
- }
Создаются буферы кадра и цвета (буфер глубины не создается за ненадобностью):
- glGenFramebuffersOES(1, &defaultFramebuffer);
- glGenRenderbuffersOES(1, &colorRenderbuffer);
- glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
- glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
- glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);
И загружается текстура. Для загрузки изображения из файла используются средства iPhone (CGImage):
- CGImageRef cgImage = [UIImage imageNamed: @"media/logo.png"].CGImage;
- if(!cgImage)
- {
- NSLog(@"Unable to load texture from file.");
- return;
- }
Далее ими же (GCContext) происходит преобразование к формату RGBA8:
- int width = CGImageGetWidth(cgImage);
- int height = CGImageGetHeight(cgImage);
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- GLuint * pixels = (GLuint*)malloc(width * height * 4);
- CGContextRef cgContext = CGBitmapContextCreate(pixels, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
- CGContextClearRect(cgContext, CGRectMake(, , width, height));
- CGContextDrawImage(cgContext, CGRectMake(, , width, height), cgImage);
И создается OpenGL текстура:
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(1, &textureID);
- glBindTexture(GL_TEXTURE_2D, textureID);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, , GL_RGBA, width, height, , GL_RGBA, GL_UNSIGNED_BYTE, pixels);
За отрисовку состояния кадра отвечает метод drawView, состоящий почти полностью из стандартных OpenGL ES команд. Сама отрисовка ведется по таймеру который активируется/деактивируется в зависимости от состояния приложения.
Напоследок разберемся, как сделать Ad Hoc сборку приложения.
Будем считать, что сертификаты и provision-профили созданы и успешно установлены. Теперь необходимо создать дополнительную конфигурацию “Distribution” (скопируем ее с конфигурации “Release”, для этого выберем в менеджере файлов проект и нажмем кнопку «Info», выберем вкладку «Configurations», выделим «Release» и нажмем кнопку «Duplicate»):

После этого перейдем на вкладку «Build» и поставим новую конфигурацию активной. В секции «Code Signing» поставим подпись сертификатом на дистрибуцию, тут же в пункте «Code Signing Entitlements» впишем «Entitlements.plist» (при сборке для AppStore делать этого не нужно):

Далее создадим этот файл. Жмем «File» -> «New file», в появившемся окне выбираем в меню пункт «Code Signing» и выбираем «Entitlements»:

Далее указываем имя для нового файла («Entitlements.plist») и создаем его. В данном файле содержится всего 1 поле — «get-task-allow», просто снимаем с него галочку.
Теперь можно собирать приложение под конфигурацией «Distribution» и отправлять полученное приложение вместе в provision-профилем пользователю. Пользователю же необходимо просто перетащить эти два файла в iTunes и синхронизировать устройство. Если все было сделано правильно — приложение установится, и будет успешно работать.
На этом, пожалуй, и все. Если к теме разработки под iPhone будет интерес — могу написать еще ряд статей, в комментариях в таком случае хотелось бы увидеть интересующие Вас темы.



комментарии (114)