В моем предыдущем уроке я обсуждал, как разрабатывать приложения для Android на C или C ++ с использованием Native Development Kit. В этом уроке я расскажу, как использовать C или C ++ вместе с Objective-C в iOS. В отличие от Android, который нуждается в специальном API (NDK) для поддержки нативной разработки, iOS поддерживает его по умолчанию. Разработка на C или C ++ более проста с iOS благодаря функции под названием Objective-C ++. Я расскажу, что такое Objective-C ++, его ограничения и как он используется для создания приложений для iOS.
Что такое Objective-C ++?
Objective-C ++ может звучать как новый язык программирования, но это не так. Это комбинация двух языков, Objective-C и C ++. Apple предоставляет Objective-C ++ в качестве удобного механизма для смешивания кода Objective-C с кодом C ++.
Objective-C близок к C, но с объектно-ориентированными функциями, реализованными в виде тонкого слоя поверх C. Это строгий расширенный набор
C, который делает любой код на C допустимой программой Objective-C.
Несмотря на то, что сейчас Swift является рекомендуемым языком для разработки приложений для iOS, все же есть веские причины использовать более старые языки, такие как C, C ++ и Objective-C. Несмотря на быстрый рост Swift, Objective-C по-прежнему является доминирующим языком на iOS из-за огромного количества существующих приложений и библиотек, уже созданных с его помощью.
Одной из причин использования Objective-C является перенос существующей программы на C / C ++, написанной для другой платформы, на iOS. Разработка кроссплатформенных приложений с использованием C или C ++ возможна при тщательном планировании. Несмотря на то, что Swift является открытым исходным кодом, он еще не полностью поддерживает другие платформы. Другой вариант использования — это возможность использовать существующие библиотеки собственного кода, которые уже доступны. Это одна из наиболее важных причин по-прежнему использовать C / C ++ / Objective-C для приложений iOS.
Использование Objective-C ++
Окончательный проект для этого урока можно найти на GitHub .
Создать проект
Откройте XCode и выберите Создать новый проект XCode .
На экране выбора шаблона выберите Single View Application на вкладке iOS-приложения и нажмите Next .
На экране параметров проекта назовите продукт HelloCpp . Введите свою организацию и идентификатор организации в обратном стиле доменного имени.
Поскольку это не совсем язык, нет возможности создать проект Objective-C ++. Доступно либо Objective-C, либо Swift. Для этого проекта выберите Objective-C. Оставьте остальные параметры такими, как они есть, нажмите « Далее» и выберите папку для сохранения проекта.
C ++
Время добавить код на C ++. Если вы впервые используете C ++, ознакомьтесь с этим руководством по языку. Посмотрите на панель Project Navigator слева. Большинство файлов заканчиваются на .h или .m . Те, которые заканчиваются на .h, являются заголовочными файлами, в то время как файлы с .m являются исходными файлами Objective-C
Создайте класс C ++, который будет вызываться из файла Objective-C. Создайте новый файл, используя пункт меню Файл -> Создать -> Файл… или нажмите N + N. В открывшемся окне шаблона файла выберите iOS -> Источник -> Файл C ++ и нажмите « Далее» .
Назовите файл « Приветствие» , оставьте флажок « Также создать заголовочный файл» и нажмите « Далее» . Сохраните файл в папке HelloCpp .
Структура проекта теперь должна выглядеть следующим образом. Не стесняйтесь перетаскивать файлы, чтобы улучшить расположение в Project Navigator .
Откройте Greeting.hpp и добавьте следующий код между строками include <stdio.h>
и #endif /* Greeting_hpp */
:
#include <string> class Greeting { std::string greeting; public: Greeting(); std::string greet(); };
Определите эти методы в Greeting.cpp , добавив следующий код после строки include "Greeting.hpp"
:
Greeting::Greeting() { greeting = "Hello C++!"; } std::string Greeting::greet() { return greeting; }
Это простой код, который создает класс с именем Greeting
с помощью одного метода с именем greet()
который возвращает строковое значение.
Objective-C с C ++
Теперь, когда вы добавили простой класс приветствия C ++, попробуйте вызвать его из Objective-C. Откройте ViewController.m и импортируйте файл заголовка Greeting.hpp :
#import "ViewController.h" #import "Greeting.hpp" ...
Объявите переменную типа Greeting
внутри блока @interface в ViewController.
@interface ViewController () { Greeting greeting; } @end
Если включен параметр « Показать проблемы в реальном времени »
, после добавления предыдущей строки кода сразу же появится сообщение о том, что имя неизвестного типа «Приветствие»
. Чтобы устранить эту проблему, переименуйте ViewController.m в ViewController.mm . Это простое соглашение об именах сообщает Xcode, что ViewController
хочет смешать Objective-C с C ++. После переименования файла ошибка должна исчезнуть.
Давайте сделаем приложение более интерактивным, добавив кнопку. Выберите Main.storyboard в Project Navigator, чтобы показать сцену View Controller. Перетащите кнопку из библиотеки объектов в центр представления, как показано ниже. Измените текст на Tap Me! ,
Создайте розетку UIButton
которая указывает на недавно созданную кнопку. Находясь на экране Main.storyboard , откройте Помощник редактора, переключив его с панели инструментов. Нажмите клавишу управления на клавиатуре и перетащите соединитель от кнопки до строки под переменной greeting
. Назовите этот выход helloButton .
Откройте ViewController.h и добавьте следующий метод IBAction
между @interface
и @end
:
- (IBAction)showGreeting;
Определите этот метод в ViewController.mm с помощью следующего кода, вставленного после функции - (void)didReceiveMemoryWarning
и перед @end
:
- (IBAction)showGreeting { NSString* newTitle = [NSString stringWithCString:greeting.greet().c_str() encoding:[NSString defaultCStringEncoding]]; [helloButton setTitle:newTitle forState:UIControlStateNormal]; }
Этот метод вызывает метод greet()
определенный в классе Greeting
C ++, и использует возвращаемое строковое значение для замены Tap Me! название кнопки. Подключите кнопку к этому действию, используя ту же технику управления + перетаскивания . Вернитесь к экрану Main.storyboard и откройте Assistant Editor с помощью панели инструментов, затем нажмите и перетащите соединитель с кнопки в - (IBAction)showGreeting
метода - (IBAction)showGreeting
. Небольшой полый кружок слева от - (IBAction)showGreeting
метода - (IBAction)showGreeting
должен быть активирован / заполнен, указывая, что Tap Me! Кнопка теперь связана с этим действием.
Создайте и запустите приложение. Обратите внимание, что кнопка отображается не в центре симулятора. Исправьте это, включив ограничения Auto Layout, используя технику Control + drag . Подключите кнопку к ее контейнеру и включите вертикальное и горизонтальное центрирование. Запустите приложение еще раз, чтобы увидеть улучшения.
Ограничения
Objective-C ++ на самом деле не объединяет Objective-C с возможностями C ++. То есть классы Objective-C не будут иметь функций, доступных для C ++ и наоборот. Следующие примеры кода иллюстрируют эти ограничения:
Вызов объекта C ++ с использованием синтаксиса Objective C не будет работать
std::string greet = [greeting greet]; // error
Конструкторы или деструкторы не могут быть добавлены к объекту Objective C
@interface ViewController () { Greeting greeting; IBOutlet UIButton *helloButton; ViewController(); // error ~ViewController(); // error } @end
Ключевые слова this
и self
не могут использоваться взаимозаменяемо
std::string greet = self->greeting.greet(); // works std::string greet2 = this->greeting.greet(); // error
Класс C ++ не может наследоваться от класса Objective C
#include <stdio.h> #include <string> #include "ViewController.h" class Greeting: public ViewController { // error std::string greeting; public: Greeting(); std::string greet(); };
Класс Objective-C не может наследоваться от класса C ++
#import "Greeting.hpp" @interface Goodbye : Greeting // error @end
Обработка исключений также не полностью поддерживается при смешивании Objective-C и C ++
Исключение, выброшенное в коде Objective C, не может быть поймано в коде C ++, в то время как исключение, выброшенное в коде C ++, не может быть пойман в коде Objective C.
double divide(int dividend, int divisor) { if ( divisor == 0 ) { throw "Cannot divide by zero!"; // will not be caught in Objective-C } return (dividend/divisor); }
Повторное использование библиотек
Возможность многократного использования существующих библиотек C / C ++ является одним из наиболее важных случаев использования нативных языков, и это простой процесс в iOS. В то время как Android все еще требует отдельного NDK, iOS уже поддерживает C и C ++.
SDL
Как и в учебнике по Android NDK , в этом примере мы будем использовать SDL. Simple DirectMedia Layer — это библиотека аппаратных абстракций с открытым исходным кодом, используемая в основном для игр или чего-либо, что связано с высокопроизводительной графикой. Он написан на C, поэтому может быть легко включен в код Objective-C.
Настройка проекта
Сначала загрузите исходный код SDL со страницы загрузки или клонируйте репозиторий Mercurial с помощью:
hg clone http://hg.libsdl.org/SDL
После завершения загрузки или клонирования создайте новый проект приложения единого представления в XCode. Назовите его HelloSDL с языком, установленным в Objective-C.
Вы начнете с нуля, поэтому в Project Navigator выберите следующие выделенные файлы и переместите их в корзину:
Удалите следующие ключи из файла Info.plist .
Добавьте проект библиотеки SDL в HelloSDL, используя пункт меню Файл -> Добавить файлы в Hello SDL
… . Перейдите к загруженной или клонированной папке SDL, в Xcode-iOS / SDL / и затем выберите SDL.xcodeproj .
Выберите основной проект HelloSDL в Навигаторе проектов и в разделе «Цели» выберите HelloSDL . Прокрутите вниз до раздела Связанные фреймворки и библиотеки .
Нажмите кнопку + , чтобы вручную добавить libSDL2.a и следующие фреймворки:
- AudioToolbox.framework
- CoreAudio.framework
- CoreGraphics.framework
- CoreMotion.framework
- Foundation.framework
- GameController.framework
- OpenGLES.framework
- QuartzCore.framework
- UIKit.framework
Используйте Ctrl + клик, чтобы выбрать несколько фреймворков. Приведите в порядок Навигатор проектов , выбрав недавно добавленные рамки и сгруппировав их с помощью пункта контекстного меню « Новая группа из выбора» .
Добавьте файл main.c в проект. Для этого не нужно создавать файл заголовка, поэтому снимите флажок Также создавать файл заголовка .
Мы будем использовать этот пример кода Холмса Футрелла из файла SDL / Xcode-iOS / Template / SDL iOS / main.c :
/* * rectangles.c * written by Holmes Futrell * use however you want */ #include "SDL.h" #include <time.h> #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 480 int randomInt(int min, int max) { return min + rand() % (max - min + 1); } void render(SDL_Renderer *renderer) { Uint8 r, g, b; /* Clear the screen */ SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); /* Come up with a random rectangle */ SDL_Rect rect; rect.w = randomInt(64, 128); rect.h = randomInt(64, 128); rect.x = randomInt(0, SCREEN_WIDTH); rect.y = randomInt(0, SCREEN_HEIGHT); /* Come up with a random color */ r = randomInt(50, 255); g = randomInt(50, 255); b = randomInt(50, 255); SDL_SetRenderDrawColor(renderer, r, g, b, 255); /* Fill the rectangle in the color */ SDL_RenderFillRect(renderer, &rect); /* update screen */ SDL_RenderPresent(renderer); } int main(int argc, char *argv[]) { SDL_Window *window; SDL_Renderer *renderer; int done; SDL_Event event; /* initialize SDL */ if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("Could not initialize SDL\n"); return 1; } /* seed random number generator */ srand(time(NULL)); /* create window and renderer */ window = SDL_CreateWindow(NULL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL); if (!window) { printf("Could not initialize Window\n"); return 1; } renderer = SDL_CreateRenderer(window, -1, 0); if (!renderer) { printf("Could not create renderer\n"); return 1; } /* Enter render loop, waiting for user to quit */ done = 0; while (!done) { while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { done = 1; } } render(renderer); SDL_Delay(1); } /* shutdown SDL */ SDL_Quit(); return 0; }
Этот код отображает прямоугольники со случайными цветами на случайных областях экрана. Скопируйте этот код в файл main.c.
Наконец, задайте для свойства « Пути поиска заголовка пользователя» папку, в которой находятся файлы заголовков SDL. Самый простой способ сделать это — создать символическую ссылку, которая указывает на папку SDL внутри проекта HelloSDL, и установить для свойства « Пути поиска заголовка пользователя» значение SDL / include / .
Убедитесь, что HelloSDL является активной схемой на панели инструментов, затем создайте и запустите проект, чтобы увидеть танцующие прямоугольники.
Вывод
Как вы видели, разработка C и C ++ в iOS проста благодаря использованию Objective-C ++. Если раньше вы программировали на C или C ++, то теперь проще перейти к разработке под iOS и использовать имеющиеся у вас навыки. Лучше всего то, что вы можете воспользоваться существующими библиотеками C / C ++, такими как мощный SDL с минимальной конфигурацией.
Я хотел бы услышать ваш опыт и мнения об использовании Objective-C ++ в комментариях ниже.