Введение
Продолжая разрабатывать «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»'а. Общий репозиторий и личный.