Введение
Продолжая разрабатывать «pod» в определённый момент приходит понимание, что проект становится большим и
Тестовый проект
Разрабатывать «pod» сам по себе занятие как минимум странное. Обычно его разработка ведётся в контексте какого-то проекта. А ещё лучше, когда для разработки «pod»'а ведётся специальный проект, покрытый тестами, и с полезными примерами использования в коде. Создадим же наш тестовый проект «Single View Application» в каталоге ~/Documents/PodSample/Project. После чего подключим к нему наш «pod». Для этого создаём в этом же каталоге файл Podfile. Результат должен выглядеть примерно так:

Заполняем Podfile:
platform :ios, '7.0' pod 'MyLibrary', :path => '~/Documents/PodSample/MyLibrary.podspec'
Являясь разработчиком «pod»'а мы можем упростить себе жизнь и после имени явно указать путь к спецификации — файлу .podspec. В результате установщик не полезет по репозиториям «spec»'ов, а возьмёт явно указанную спецификацию по указанному пути. В принципе, можно не указывать имя файла MyLibrary.podspec — достаточно указать каталог где находится файл спецификации вашего «pod»'а, установщик сам его найдёт. Так же ничто не мешает использовать относительные пути, например:
platform :ios, '7.0' pod 'MyLibrary', :path => '..'
Далее закрываем XCode, или хотя бы тестовый проект MyPodExample.xcodeproj.
Устанавливаем наш «pod»:
$ cd ~/Documents/PodSample/Project/ $ pod install Analyzing dependencies Fetching podspec for `MyLibrary` from `~/Documents/PodSample/MyLibrary.podspec` Downloading dependencies Using MyLibrary (0.0.1) Generating Pods project Integrating client project
Установщик генерирует нам «workspace», куда добавляет тестовый проект и новый проект «Pods». Открываем workspace MyPodExample.xcworkspace и наблюдаем нечто похожее:

Выделяем модули
Предположим наш полезный «pod» уже умеет соединяться с сервером, обрабатывать JSON и хранить некие данные в своём внутреннем хранилище. Создадим набор классов и объявим немного методов в их публичных интерфейсах. Результат лежит на GitHub с тэгом mixed.
Разделение «pod»'а на модули проходит в два этапа. Сначала приводится в порядок код, для чего мы разносим различные сущности по собственным файлам. После чего обновляем «spec» — описываем получившиеся модули в блоках «subspec» и проставляем их зависимости друг от друга параметром «dependency»:
Pod::Spec.new do |s| s.name = "MyLibrary" s.version = "0.0.2" s.summary = "Example of creating own pod." s.homepage = "https://github.com/username/MyCustomPod" s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { "Username" => "username@mail.domain" } s.platform = :ios, 7.0 s.source = { :git => "https://github.com/username/MyCustomPod.git", :tag => s.version.to_s } s.framework = 'Foundation' s.requires_arc = true s.default_subspec = 'Core' # Модуль по умолчанию называется Core s.subspec 'Core' do |core| core.source_files = 'Classes/AKClass.{h,m}' core.public_header_files = 'Classes/*.h' core.dependency 'MyLibrary/Connection' core.dependency 'MyLibrary/Provider' end s.subspec 'Provider' do |provider| provider.source_files = 'Classes/AKProvider.{h,m}' provider.frameworks = 'MapKit', 'CoreData' # Добавлены зависимости от фрэймворков provider.platform = :ios, 5.0 # Этот модуль может запускаться и на iOS 5.0 end s.subspec 'AccessToken' do |access_token| access_token.source_files = 'Classes/AKAccessToken.{h,m}' access_token.libraries = 'xml2' # Зависимость от библиотеки access_token.xcconfig = { 'HEADER_SEARCH_PATHS' => '$(SDKROOT)/usr/include/libxml2' } # Где искать заголовочные файлы end s.subspec 'Parser' do |parser| parser.source_files = 'Classes/AKParser.{h,m}' end s.subspec 'Storage' do |storage| storage.source_files = 'Classes/AKStorage.{h,m}' storage.dependency 'MyLibrary/AccessToken' end s.subspec 'Connection' do |connection| connection.source_files = 'Classes/AKConnection.{h,m}' connection.dependency 'MyLibrary/Storage' connection.dependency 'MyLibrary/Parser' end end
Для модуля «Provider» указываем необходимость подключить два фрэймворка — «MapKit» и «CoreData». А для модуля «AccessToken» необходимо подключить библиотеку «xml2», заголовочные файлы искать по указанном пути: $(SDKROOT)/usr/include/libxml2
Говорят, что с версии «CocoaPods v0.17» модули больше не наследуют неявно значения «source_files» у базового «spec». Чтобы вернуть данную возможность необходимо завести «Core» модуль который включает базовые исходники необходимые создаваемым модулям.
Так же существует возможность разбивать модули на подмодули:
… s.subspec 'Connection' do |сonnection| сonnection.source_files = 'Classes/AKConnection.{h,m}' сonnection.dependency 'MyLibrary/Storage' сonnection.dependency 'MyLibrary/Parser' сonnection.subspec 'Cache' do |cache| cache.source_files = 'Classes/AKCache/*.{h,m}' end end …
Так же можно указать платформу и её версию на которых модуль сможет работать. В данном случае мы указали, что модуль Provider запустится даже на «iOS 5.0».
Проверяем синтаксис:
$ pod spec lint ~/Documents/PodSample/MyLibrary.podspec --quick -> MyLibrary (0.0.2) Analyzed 1 podspec. MyLibrary.podspec passed validation.
И коммитим изменения в git, ставим тэг и отправляем на GitHub:
$ git add MyLibrary.podspec && git commit -m "Spec sliced on subspecs" $ git add -A && git commit -m "Sliced code" $ git tag "0.0.2" $ git push origin master --tags
Проверяем весь проект:
$ pod spec lint ~/Documents/PodSample/MyLibrary.podspec -> MyLibrary (0.0.2) Analyzed 1 podspec. MyLibrary.podspec passed validation.
Использование модуля
Чтобы использовать только необходимые модули достаточно их перечислить в Podfile:
platform :ios, '7.0' pod 'MyLibrary/Storage' pod 'MyLibrary/Parser'
Если не указать ни одного модуля:
platform :ios, '7.0' pod 'MyLibrary'
то pod install установит исходники всех модулей. Если же в данном случае нужно установить только исходники «Core» модуля, то в «spec»'е указывается его имя в параметре «default_subspec» — см. пример выше.
Укажем в нашем Podfile зависимость тестового проекта от модуля «Provider» и заодно укажем нужную нам сейчас версию — «0.0.2»:
platform :ios, '7.0' pod 'MyLibrary/Provider', :path => '..' pod 'MyLibrary/Connection', :path => '..'
И обновим зависимости проекта:
$ cd ~/Documents/PodSample/Project/ $ pod update Analyzing dependencies Fetching podspec for `MyLibrary` from `..` Fetching podspec for `MyLibrary` from `..` Downloading dependencies Installing MyLibrary (0.0.2) Generating Pods project Integrating client project
Подключение стороннего «pod»'а
Иногда бывает так, что разработка «pod»'а доходит до момента, когда хочется
Pod::Spec.new do |s| s.name = "MyLibrary" s.version = "0.0.3" s.summary = "Example of creating own pod." s.homepage = "https://github.com/username/MyCustomPod" s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { "Username" => "username@mail.domain" } s.platform = :ios, 7.0 s.source = { :git => "https://github.com/username/MyCustomPod.git", :tag => s.version.to_s } s.framework = 'Foundation' s.requires_arc = true s.default_subspec = 'Core' # Модуль по умолчанию называется Core s.subspec 'Core' do |core| core.source_files = 'Classes/AKClass.{h,m}' core.public_header_files = 'Classes/*.h' core.dependency 'MyLibrary/Connection' core.dependency 'MyLibrary/Provider' end s.subspec 'Provider' do |provider| provider.source_files = 'Classes/AKProvider.{h,m}' provider.frameworks = 'MapKit', 'CoreData' # Добавлены зависимости от фрэймворков provider.platform = :ios, 5.0 # Этот модуль может запускаться и на iOS 5.0 end s.subspec 'AccessToken' do |access_token| access_token.source_files = 'Classes/AKAccessToken.{h,m}' access_token.libraries = 'xml2' # Зависимость от библиотеки access_token.xcconfig = { 'HEADER_SEARCH_PATHS' => '$(SDKROOT)/usr/include/libxml2' } # Где искать заголовочные файлы end s.subspec 'Parser' do |parser| parser.source_files = 'Classes/AKParser.{h,m}' end s.subspec 'Storage' do |storage| storage.source_files = 'Classes/AKStorage.{h,m}' storage.dependency 'MyLibrary/AccessToken' end s.subspec 'Connection' do |connection| connection.source_files = 'Classes/AKConnection.{h,m}' connection.dependency 'MyLibrary/Storage' connection.dependency 'MyLibrary/Parser' connection.dependency 'AFNetworking' # Добавлена зависимость от внешнего "pod"'а end end
При интеграции могут возникнуть проблемы с версиями платформ, используемых вами и внешними «pod»'ами. Успешно решив их обновляем зависимости (крайне желательно при закрытом XCode или проекте):
$ cd ~/Documents/PodSample/Project/ $ pod update Analyzing dependencies Fetching podspec for `MyLibrary` from `..` Fetching podspec for `MyLibrary` from `..` Downloading dependencies Installing AFNetworking (2.0.1) Installing MyLibrary (0.0.3) Generating Pods project Integrating client project
Скачаются и подключатся необходимые «pod»'ы, настроится workspace. Теперь можно в своём «pod»'е использовать силу всех прочих
Продолжение следует.
Запланировано:
Часть 3. Публикация своего «pod»'а. Общий репозиторий и личный.