Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР 116, АВГУСТ 2008 г.

XCoding под iPhone

Дмитрий «Dem@n» Тарасов (admin@dtarasov.ru)

Хакер, номер #116, стр. 116-090-1

Введение в разработку ПО для iPhone

Прошел уже год с момента выпуска iPhone 1.0. Можно долго рассуждать по поводу значимости этого события, а также критиковать маркетинговую политику Apple по отношению к ряду стран, в числе которых и Россия. Но факт есть факт: iPhone – революционное мобильное устройство, задающее планку для остальных производителей. Попытаемся разобраться, как писать и распространять для него программные продукты.

Сегодня сложно найти в метро такой вагон, в котором не было бы владельца трендовой мобилки. Популярность устройства привела к формированию целого сообщества пользователей iPhone, среди которых оказалось много опытных программистов, за короткий срок умудрившихся взломать защиту устройства от использования SIM-карт любых операторов сотовой связи. После публикации средств «jailbreaking» (модификация прошивки с целью снятия ограничений) разлоченные iPhone можно без проблем заказать в интернете, а также купить на рынке электронной техники. Для нас с тобой это означает возможность приложить свои жилистые лапы к процессу разработки ПО для iPhone.

Разработка приложений с использованием движка Safari

До официальной публикации SDK у разработчиков не было возможности легальной разработки native – приложений для iPhone и iPod Touch. Учитывая огромный интерес к iPhone, Apple пошла на компромисс: позволила сторонним разработчикам создавать так называемые виджеты – приложения, выполняемые в веб–браузере Safari, интегрированном в iPhone и iPod Touch. Основным отличием виджетов от native–приложений является необходимость написания кода не на Objective C, а с использованием стандартных веб–технологий вроде HTML, CSS, JavaScript и AJAX. С точки зрения пользователя такое приложение отличается тем, что выполняется в веб-браузере и открывается не путем выбора иконки из главного меню устройства, а при выборе закладки. Для ознакомления с процессом создания и развертывания виджетов для iPhone рекомендую почитать книгу «Professional iPhone and iPod Touch Programming», а также заглянуть на http://developer.apple.com/webapps/.

Неофициальный и официальный методы разработки

Отсутствие официальной возможности создавать ПО не остановило энтузиастов. Они подготовили средства разработки, позволяющие создавать полноценный софт для JailBreaked iPhone. В процессе JailBreaking на аппарат устанавливается софтина с немудреным названием Installer. С ее помощью пользователи могут скачивать и устанавливать необходимый софт из каталога, который формируется из репозиториев (их адреса прописываются вручную в Installer). Так что JailBreaking – не только разлочка, но и процедура, позволяющая получить полный доступ к файловой системе iPhone. Описание процесса без труда можно найти в Сети, поэтому мы не будем на этом останавливаться.

Софт, распространяющийся через Installer, написан с использованием «неофициального» процесса разработки. До недавнего времени иного пути создания и даже установки стороннего ПО в iPhone не было. Но в марте этого года Apple осчастливили-таки общественность публикацией первой беты SDK. С тех пор на офсайте разработчиков Apple периодически публикуются новые версии беты SDK и документации (на момент написания статьи наиболее актуальной была восьмая). SDK представляет собой IDE XCode, набор необходимых библиотек, эмулятор и другие инструменты. В статье мы рассмотрим обе методики разработки софта, но предварительно нужно сказать несколько слов о технологиях, использующихся при разработке ПО для iPhone.

iPhone OS

Технологии, лежащие в основе ОС, принято представлять в виде слоев. Чем выше слой – тем выше уровень абстракции и тем чаще он используется для разработки. Нижние содержат технологии, предназначенные для выполнения низкоуровневых функций вроде базового ввода/вывода. При этом многие технологии ОС близки по духу к использующимся в настольной операционке.

Нижним слоем архитектуры в нашем случае является Core OS. Ядро iPhone OS базируется на адаптированном варианте ядра Mac OS X. Как водится, ядро служит для управления файловой системой, потоками, базовыми интерфейсами, межпроцессорным и сетевым взаимодействием, драйверами, виртуальной памятью т.д. Уровнем выше расположен Core Services Layer, предоставляющий приложениям необходимые фундаментальные сервисы (типы данных, port’n’socket communication, потоки и т.д.). Разработчику редко когда приходится обращаться к этому слою напрямую, но вышележащие слои делают так постоянно. Media Layer содержит аудио-, видео- и графические технологии, играющие важную роль в iPhone OS. Данный уровень представляет собой удобный фреймворк, позволяющий быстро и легко использовать мультимедиа при разработке.

Самый верхний слой – Cocoa Touch Layer. Он предоставляет высокоуровневый API, предназначенный для создания графических приложений, а также для управления событиями. Любые пользовательские интерфейсы iPhone OS и взаимодействие с пользователем проектируются с использованием Cocoa Touch. Технология является модифицированной версией фреймворка Cocoa, который используется при разработке ПО для Mac OS X. Поэтому она имеет ряд схожих с ним черт, но содержит и нововведения, связанные с кардинально отличающимся механизмом ввода информации в iPhone (мышку и клавиатуру заменяют прикосновения к экрану) и необходимые для доступа к встроенным в iPhone приложениям вроде Contacts и Photos.

Ищите леопарда

Чтобы программировать под iPhone, нужен Mac с установленной Mac OS X Leopard. Грустно, но это так. Вообще говоря, можно развернуть среду разработки на Unix и даже пытаться писать из-под VMWare, но это связано с рядом сложностей, которые мы не в состоянии охватить в рамках журнального материала, поэтому здесь и далее мы будем полагать, что работа идет в Mac OS X Leopard. Кроме того, необходимо установить и сконфигурировать SDK. Описание процесса настройки рабочей станции для «неофициальной» разработки можно прочитать в замечательной книжке «iPhone Open Application Development», которую легко найти в Сети.

Objective C

При разработке приложений для iPhone OS, а также MacOS 10.5 и выше используетсяязык программирования Objective C 2.0. Он является своеобразной надстройкой над ANSI C, предназначенной для гибкого объектно-ориентированного программирования. Не совсем понятно, чем Apple не угодил С++. Многие концепции Objective C заимствованы у одного из первых объектно-ориентированных языков Smalltalk. Тем не менее, программа для iPhone может содержать как код на Objective C, так и на C или C++.

При компиляции используются инструменты GNU Compilers Collection, которые распознают принадлежность кода к конкретному подвиду GNU C/C++ по расширению файла. В частности, C – код содержится в файлах с расширением *.c; C++ – код в *.mm; Objective C – в *.m.

Особенности Objective C

В Objective C, как и в C++, присутствуют классификаторы доступа к переменным – членам класса (@private, @protected, @public и @package). Разница в том, что эти классификаторы действуют только для объектов того же класса или его наследников. Для доступа к переменным – членам из других классов – необходимо реализовать соответствующие методы. Например, чтобы иметьвозможность получать размеры объекта класса прямоугольника из объекта класса окна, понадобится реализовать в первом метод, возвращающий размеры.

Отличительным типом данных в Objective C является тип id, использующийся при динамической типизации.

Конструкция вида id anObject – это объявление указателя на объект. Ключевым словом для нулевого объекта (то есть для указателя, который ни на что не указывает) будет nil. Сам по себе id не несет абсолютно никакой информации об объекте (помимо того, что это, собственно, объект). Необходимые знания о методах и переменных – членах конкретного объекта – получаются при использовании так называемой isa-переменной, указывающей, к какому конкретно классу он относится. Само собой, этот подход имеет смысл применять только, если заранее неизвестно, к какому классу относится объект (или их совокупность).

Object Messaging

В Objective C принята концепция – объектам оправляются сообщения в случае необходимости вызова какого-либо метода. Скажем, конструкция [receiver message] означает, что объекту receiver посылается сообщение message. По своей сути оно является именем метода с указанием его параметров. К примеру, вызов метода setWidth(int) объекта класса CRect выглядит так:

[myRect setWidth:20.0];

Как видно, параметры метода отделяются от его названия двоеточием. Если обязательных параметров несколько, они также отделяются друг от друга с помощью двоеточия:

[myRect setOrigin:30.0 :50.0]

Необязательные аргументы при этом разделяются запятыми:

[receiver makeArray:array, member1, member2, member3]

Здесь метод makeArray имеет один обязательный параметр – array и 3 необязательных – member1, member2 и member3.

Как и в C, методы могут возвращать значения. В следующем примере булевой переменнойisCompleted возвращается значение булевого метода isCompleted:

BOOL isCompleted;

isCompleted = [myOperation isCompleted];

Обрати внимание, что имя переменной и метода могут совпадать. Сообщения бывают вложенными, например, одному объекту прямоугольника можно присвоить размеры другого:

[myRect setSize:[anotherRect size]];

Не запрещается посылать сообщения nil-объектам. Иногда это полезно, например, когда необходимо узнать, инициализирован ли объект. Сообщение, вызывающее возвращающий значение метод, будет равно нулю.

Создание объектов

В Objective C объявление класса обязательно должно содержаться в файле-заголовке с расширением *.h, а реализация – в файле *.m. Объявление класса выделяется с помощью директивы @interface, а реализация – директивой @implementation. Объявление простого класса может выглядеть, например, так:

#import <UIKit/UIKit.h>

@interface SimpleClass : NSObject {

//объявление переменных

}

//объявление свойств и методов

@end

Выделение памяти для нового объекта осуществляется путем отправки сообщения alloc классу, экземпляр которого требуется создать. Создание экземпляра класса Rectangle может выглядеть так:

Id myRect;

myRect = [Rectangle alloc];

Метод alloc выделяет память для объекта, а также инициализирует нулевыми значениями все его переменные-члены – за исключением переменной isa, указывающей на принадлежность объекта к конкретному классу. Чтобы можно было использовать объект, необходимо провести более тщательную инициализацию. Обычно она выполняется путем вызова метода из семейства init:

myRect = [[Rectangle alloc] init]

Подобная инициализация обязательна для кода, содержащего отправку объекту сообщений. Вообще, существует несколько разновидностей методов инициализации. Каждый из них приемлем для объектов конкретного класса, но все начинаются с init. Например, инициализацию класса Rectangle на самом деле следовало бы проводить с помощью метода initWithPosition, принимающего аргумент size.

Для получения подробной информации по Objective C советую ознакомиться с материалами сайта http://developer.apple.com/iphone, а также почитать документ «The Objective-C 2.0 Programming Language», который можно там же и скачать.

Неофициальный Hello World

Рассмотрим процесс создания несложного приложения с использованием неофициального SDK. Информацию по установке и настройке можно получить в книге «iPhone Open Application Development» либо на http://code.google.com/p/iphone-dev.

Анатомия любого приложения для iPhone проста до крайности. Приложение, по сути, – это директория с именем вида HelloWorld.app, содержащая исполняемый файл приложения, файл манифеста и ресурсы.

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

  • Default.png – картинка с расширением 320х480 пикселей, отображающаяся в устройстве в момент инициализации приложения
  • HelloWorld – собственно, исполняемый файл приложения
  • Icon.png – иконка приложения, отображающаяся в SpringBoard
  • Info.plist – своего рода манифест приложения, файл, подготовленный в XML-формате и содержащий информацию, необходимую для инициализации приложения.

Наличие файлов Default.png, Icon.png и Info.plist обязательно для успешного старта приложения.

Проект же программы примерно выглядит так:

  • HelloWorld.app – созданная вручную директория, куда мы поместили ресурсы, исполняемый файл и манифест
  • main.m – файл, содержащий код функции main, с которой традиционно для C начинается выполнение программы
  • HelloWorld.h и HelloWorld.m – исходники класса приложения
  • MainView.h и MainView.m – исходники окна приложения
  • Makefile – файл, содержащий команды для sdk, необходимые для компиляции и сборки приложения

Шаблон проекта вместе с указанными файлами можно скачать по адресу http://dtarasov.ru/iphone/files/helloworld.rar или взять на нашем крутом DVD.

Рассмотрим исходники проекта поближе:

main.m:

#import <UIKit/UIKit.h>

#import “HelloWorld.h”

int main(int argc, char** argv)

{

NSAutoreleasePool* pool =

[[NSAutoreleasePool alloc] init];

return UIApplicationMain(argc,argv,

[HelloWorld class]);

}

Каждое приложение для iPhone содержит такое определение функции main. В первой и второй строках содержится директива #import, которая выполняет схожую с #inlude функцию. Но помимо простого подключения файла, #import следит за тем, чтобы заголовок класса не включался в проект более одного раза, заменяя тем самым стандартный workaround:

#ifndef _MYCLASS_H

#define _MYCLASS_H

...

#endif

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

HelloWorld.h:

#import <CoreFoundation/CoreFoundation.h>

#import <UIKit/UIKit.h>

@interface HelloWorld : UIApplication

{

UIWindow* window;

UIView* mainView;

}

-(void)applicationDidFinishLaunching:

(NSNotification*)aNotification’

@end

В этом примере объявляется класс HelloWorld, который наследуется от UIApplication. Объект создается из функции main. Переменные-члены данного класса – это объекты классов UIWindow и UIView. Перед тем, как отобразить элементы пользовательского интерфейса, необходимо создать окно, которое сможет их содержать, и наполнить его контентом. Переменная window необходима для создания, собственно, окна, а mainView, являющаяся объектом класса UIView, – для наполнения окна конкретным содержанием. При этом окно может содержать несколько переменных класса UIView. Метод applicationDidFinishLaunching унаследован от UIApplication, который вызывается после загрузки приложения в память. Он часто переопределяется для выполнения операции начального отображения пользовательского интерфейса следующим образом:

HelloWorld:

#import “HelloWorld.h”

#import “MainView.h”

@implementation HelloWorld

-(void) applicationDidFinishLaunching:

(NSNotification*) aNotification

{

Window = [[UIWindow alloc]

initWithContentRect:[UIHardware

fullScreenApplicationContentRect]];

CGRect windowRect = [UIHardware

fullScreenApplicationRect];

windowRect.origin.x = windowRect.origin.y = 0.0f;

mainView = [[MainView alloc]

initWithFrame:windowRect];

[window setContentView: mainView];

[window orderFront: self];

[window makeKey: self];

[window _setHidden: NO];

}

@end

Здесь мы создали окно, инициализировали, а также поместили в него контент, созданный объектом класса MainView.

MainView.h:

#import <CoreFoundation/CoreFoundation.h>

#import <UIKit/UIKit.h>

#import <UIKit/UITextView.h>

@interface MainView : UIView

{

UITextView* textView;

}

А тут мы помещаем в определение MainView переменную-член класса UITextView. Она понадобится для отображения текста.

MainView.m:

#import “MainView.h”

@implementation MainView

-(id)initWithFrame:(CGRect)rect

{

If((self==[super initWithFrame:rect])!=nil)

{

textView = [[UITextView alloc]

initWithFrame: rect];

[textView setTextSize: 18];

[textView setText:@”Hello, World”];

[self addSubview: textView];

}

return self;

}

@end

После успешной инициализации объекта MainView мы создаем новый объект, унаследованный от UITextView, который в свою очередь наследуется от UIVew. UITextView позволяет настраивать параметры отображаемого текста, что мы и делаем. А затем «накладываем» textView на mainView.

На этом этапе приложение готово к сборке. Нужно только соответствующим образом подготовить makefile (см. пример из указанной выше ссылки).

Все, – открываем консоль, набираем команды make и make package. Наше приложение готово к заливке в iPhone.

Для этого в устройстве должны быть установлены пакеты BSD Subsystem и OpenSSH (можно найти в инсталлере). На устройство можно передавать файлы посредством scp. Чтобыперенести наше приложение в iPhone, выполняем следующую команду:

scp –r HelloWorld.app root@iPhone_ip:/Applications,

где iPhone_ip – ip устройства в локальной WiFi-сети. В ответ появится запрос пароля. Для iPhone первого поколения следует ввести «alpine». Чтобы иконка приложения появилась в меню устройства, нужно либо перезапустить его, либо приконнектиться к нему по ssh и выполнить команду $killall SpringBoard.

Использование официального SDK

Официальный набор инструментов можно скачать, зарегистрировавшись на http://developer.apple.com/iphone. Там же доступна документация по использованию и общим вопросам разработки для iPhone 2.0. Важно понимать, что созданный с использованием официального SDK софт ориентирован на запуск под iPhone версии 2.0. На момент написания статьи получить прошивку 2.0 и загрузить написанное в XCode-приложение (IDE, идущее в комплекте с SDK) могли лишь разработчики, участвующие в Apple Developer Program. Проблема в том, что найти человека, которому удалось стать участником Apple Developer Program, автору не удалось. Это может быть связано с тем, что ADP на момент подготовки материала еще не была запущена, либо с тем, что на период бета-тестированя SDK Apple решили подстраховаться и дать возможность полноценной разработки ПО лишь избранным компаниям. Вероятнее всего, к моменту, когда ты прочтешь эти строки, финальная версия SDK уже станет доступна и внесет ясность относительно перспектив софта, написанного с его использованием.

DVD

Упомянутые в статье доки, сорцы и прочий полезный стафф, как обычно, ждут тебя на нашем диске!

Содержание
загрузка...
Журнал Хакер #151Журнал Хакер #150Журнал Хакер #149Журнал Хакер #148Журнал Хакер #147Журнал Хакер #146Журнал Хакер #145Журнал Хакер #144Журнал Хакер #143Журнал Хакер #142Журнал Хакер #141Журнал Хакер #140Журнал Хакер #139Журнал Хакер #138Журнал Хакер #137Журнал Хакер #136Журнал Хакер #135Журнал Хакер #134Журнал Хакер #133Журнал Хакер #132Журнал Хакер #131Журнал Хакер #130Журнал Хакер #129Журнал Хакер #128Журнал Хакер #127Журнал Хакер #126Журнал Хакер #125Журнал Хакер #124Журнал Хакер #123Журнал Хакер #122Журнал Хакер #121Журнал Хакер #120Журнал Хакер #119Журнал Хакер #118Журнал Хакер #117Журнал Хакер #116Журнал Хакер #115Журнал Хакер #114Журнал Хакер #113Журнал Хакер #112Журнал Хакер #111Журнал Хакер #110Журнал Хакер #109Журнал Хакер #108Журнал Хакер #107Журнал Хакер #106Журнал Хакер #105Журнал Хакер #104Журнал Хакер #103Журнал Хакер #102Журнал Хакер #101Журнал Хакер #100Журнал Хакер #099Журнал Хакер #098Журнал Хакер #097Журнал Хакер #096Журнал Хакер #095Журнал Хакер #094Журнал Хакер #093Журнал Хакер #092Журнал Хакер #091Журнал Хакер #090Журнал Хакер #089Журнал Хакер #088Журнал Хакер #087Журнал Хакер #086Журнал Хакер #085Журнал Хакер #084Журнал Хакер #083Журнал Хакер #082Журнал Хакер #081Журнал Хакер #080Журнал Хакер #079Журнал Хакер #078Журнал Хакер #077Журнал Хакер #076Журнал Хакер #075Журнал Хакер #074Журнал Хакер #073Журнал Хакер #072Журнал Хакер #071Журнал Хакер #070Журнал Хакер #069Журнал Хакер #068Журнал Хакер #067Журнал Хакер #066Журнал Хакер #065Журнал Хакер #064Журнал Хакер #063Журнал Хакер #062Журнал Хакер #061Журнал Хакер #060Журнал Хакер #059Журнал Хакер #058Журнал Хакер #057Журнал Хакер #056Журнал Хакер #055Журнал Хакер #054Журнал Хакер #053Журнал Хакер #052Журнал Хакер #051Журнал Хакер #050Журнал Хакер #049Журнал Хакер #048Журнал Хакер #047Журнал Хакер #046Журнал Хакер #045Журнал Хакер #044Журнал Хакер #043Журнал Хакер #042Журнал Хакер #041Журнал Хакер #040Журнал Хакер #039Журнал Хакер #038Журнал Хакер #037Журнал Хакер #036Журнал Хакер #035Журнал Хакер #034Журнал Хакер #033Журнал Хакер #032Журнал Хакер #031Журнал Хакер #030Журнал Хакер #029Журнал Хакер #028Журнал Хакер #027Журнал Хакер #026Журнал Хакер #025Журнал Хакер #024Журнал Хакер #023Журнал Хакер #022Журнал Хакер #021Журнал Хакер #020Журнал Хакер #019Журнал Хакер #018Журнал Хакер #017Журнал Хакер #016Журнал Хакер #015Журнал Хакер #014Журнал Хакер #013Журнал Хакер #012Журнал Хакер #011Журнал Хакер #010Журнал Хакер #009Журнал Хакер #008Журнал Хакер #007Журнал Хакер #006Журнал Хакер #005Журнал Хакер #004Журнал Хакер #003Журнал Хакер #002Журнал Хакер #001