Xcode: управляем зависимостями собственных библиотек в проектах. Cocoapods advanced

в 12:17, , рубрики: cocoapods, objective-c, xcode, разработка под iOS, метки: , , ,

Cocoapods – это менеджер зависимостей библиотек в Xcode проектах. Я не буду рассказывать, как с его помощью подключить в проект уже существующую библиотеку, информации достаточно, в том числе и эта статья на Хабре. Я расскажу что делать, если вы не нашли нужную вам библиотеку в списке, или, что ещё хуже, вы хотите создать свою библиотеку и, как вариант, не делать её доступной.

Часть I: подключаем библиотеки через podfile

Для начала стоит посмотреть, какие возможности даёт нам Cocoapods, для подключения библиотеки в проект (через podfile):

  1. Подключить библиотеку из списка поддерживаемых:
    pod 'Reachability'
    pod 'AFNetworking/Reachability'
    pod 'JSONKit',       '~> 1.4'
    

    Самый простой способ (он же основной), при этом можно указать привязку к конкретной версии и подключить не всю библиотеку, а только её часть (через subspec)

  2. Подключить библиотеку, но при этом указать путь к спецификации
    pod 'ZipKit', :podspec => 'ZipKit.podspec'
    

    Можно использовать тогда, когда существующая Cocoapods спецификация вас каким-то образом не устраивает (например, в спецификации к библиотеке стоит iOS 6.1, а у вас в проекте Deployment target выставлен в 6.0). Сохраняем себе спецификацию, редактируем её под свои нужды, сохраняем в корень проекта – в результате у вас всё работает, и при этом нет необходимости добавлять потенциально вредные изменения в публичную спецификацию.

  3. Подключить библиотеку по локальному пути (вместе со спецификацией):
    pod 'SuperLibrary', :path => 'Submodules/SuperLibrary'
    

    Этот вариант уже интереснее, так как можно указать путь к совместному коду (subversion external, git submodule...). При таком способе файлы библиотеки включаются в проект со ссылками на этот путь, что позволяет нам редактировать библиотеку и сохранять измения в системе контроля версий. Более подробно вернёмся к этому позже

  4. Подключить библиотеку (вместе со спецификацией), расположенную в системе контроля версий, или просто по ссылке на архив:
    pod 'SuperLibrary', :git => 'git@bitbucket.org:bestcompany/SuperLibrary.git', :branch => 'development'
    

    Основное отличие от предыдущего пункта в том, что редактировать исходный код библиотеки уже нельзя (технически можно, однако при установке зависимостей в проект будут просто добавлены копии файлов, которые никак не будут ссылаться на оригинал и будут переписаны на оригинальные файлы при последующем обновлении зависимостей)

Часть II: пишем спецификацию к собственной библиотеке – «как 2 байта переслать»

Создать спецификацию просто:

pod spec create SuperLibrary

Открываем сгенерированный файл, заполняем сгенерированные разделы, читая комментарии, при затруднениях обращаемся к документации.
И здесь стоит вспомнить про такой механизм, как модули библиотеки (subspec). В кратце, разбиваем нашу библиотеку на некоторые логические модули (в том числе связанные между собой), описываем ресурсы, исходные коды, зависимости по-отдельности, например:

s.subspec 'Data' do |ds|
    ds.source_files = 'Data/*.{h,m}', 'Data/Categories/*.{h,m}', 'Data/Objects/*.{h,m}'
    ds.resources = 'Data/SuperLibrary.xcdatamodeld'
    ds.dependency 'MagicalRecord'
    ds.dependency 'SuperLibrary/Resources'
  end

Доступ к модулю осуществляется через MasterSpec/Subspec, одни модули внутри могут зависеть от других внутри одной спецификации, допускается многоуровневая вложенность. Осталось указать модуль, который будет подключен по умолчанию, например

s.default_subspec = 'Controllers'

И всё, библиотеку можно подключать по частям, например только сетевое ядро, не затрагивая ресурсы и Unit-тесты.
Несколько советов:
Схема базы данных (*.xcdatamodeld и иже с ними) это ресурс а не исходный код, с недавней версии cocoapods подключается нормально, в том числе вместе с версиями схемы.
Зависимости своей библиотеки от других желательно прописывать без привязки к конкректной версии (за исключением, например, Facebook-iOS-SDK, API которой меняется слишком часто).

Часть III: свой репозиторий спецификаций «с шахматами и поэтессами»

Библиотеки подключать знаем как, создавать спецификацию умеем, идея версий библиотек нам нравится, но делиться библиотеками не будем. Весьма частая ситуация в маленьких и больших компаниях, есть много проектов, на них используется совместный код, хорошо бы их оформить как библиотеки и работать с версиями так же просто, как и с обычными cocoapods библиотеками. И тут на помощь приходит приватные репозитории. Что нам для этого потребуется:

  1. Создаём новый репозиторий для спецификаций, который будет доступен вашей команде. Плохая новость, для репозитория спецификаций поддерживается только git. (Хорошая новость, на git должен быть только репозиторий спецификаций, сами библиотеки по-прежнему будут доступны по git/svn или даже по обычной ссылке на архив). Добавляем его в cocoapods простой командой из консоли:
    pod repo add Private-Cocoapods git@bitbucket.org:bestcompany/cocoapods-specs.git
    

    Осталось дело за малым, создаём в корне этого репозитория папку с именем библиотеки, в ней создаём папку с версией библиотеки, куда уже помещаем непосредственно саму спецификацию.
    Xcode: управляем зависимостями собственных библиотек в проектах. Cocoapods advanced
    Всё, осталось отправить эти изменения на репозиторий и последующие команды pod install (или pod update) будут работать с нашей библиотекой так же, как и с официальной, то есть подключать pod можно будет просто по имени библиотеки.

Часть IV: Подключаем всё вместе, или как можо построить процесс разработки

И один из сценариев, как с этим можно успешно работать. Предпосылка: ведётся разработка нескольких продуктов (одновременно или нет, не важно), в приложениях есть совместно используемый код (библиотеки), разработка каждой библиотеки ведётся в собственной ветке репозитория.
Итак, нам надо, чтобы в корне каждой библиотеки лежал актуальный podspec файл, версия в podspec файле идёт с постфиксом dev, параметр source ссылается на текущую ветку, например:

Pod::Spec.new do |s|
  s.name         = "SuperLibrary"
  s.version      = "1.0.5-dev"
  s.source       = { :git => "ssh://git@bitbucket.org:bestcompany/my-super-library.git"}

Таким образом, при подключении этой версии непосредственно из репозитория, мы будем иметь пометку dev, говорящую о том, что версия не готова. После тестирования этот библиотеки создаём tag с именем версии (проверить версию, и, если необходимо, поднять минорную/мажорную версию), копируем podspec файл в наш собственный репозиторий спецификаций, убирая приставку dev из версии и указав конкретный таг в репозитории, который мы только что создали:

Pod::Spec.new do |s|
  s.name         = "SuperLibrary"
  s.version      = "1.1.0"
  s.source       = { :git => "ssh://git@bitbucket.org:bestcompany/my-super-library.git", :tag => "SuperLibrary_v1.1.0" }

Всё, осталось в репозитории библиотеки выставить версию на один больше не убирая постфикс dev (1.1.1-dev в нашем случае) и отправить все изменения в репозиторий.
Разработка, обычно, это процесс бесконечный, и необходимость править библиотеки возникает очень часто. Для таких случаев можно всегда хранить ссылку на текущую версию библиотеки в репозитории через сабмодуль в Git (external в Subversion). При этом в podfile конкретного продукта всегда указана стабильная версия (podspec хранится на нашем репозитории спецификаций), но рядом закоментированная строчка на текущую версию:

	#pod 'SuperLibrary', :path => 'Submodules/SuperLibrary'
	pod 'SuperLibrary'

В случае необходимости внести изменения в библиотеку, убираем комментарий со строчки, обновляем библиотеку до последней версии в репозитории, делаем pod update в консоли и всё, можно смело изменять и тестировать. Перед подготовкой приложения в публикацию стоит зафиксировать все версии библиотек (то есть создать новые версии для всех изменённых библиотек и подключить их из нашего репозитория спецификаций). Всегда проверяйте podfile.lock на то, какие версии библиотек используются, наш постфикс -dev очень помогает определить, что версия библиотеки может быть не протестирована.
И да, делать pod update как часть процесса сборки приложения явно не стоит (по-крайней мере на стадии подготовки версии к релизу, так как из-за обновления библиотеки обязательно что-то перестанет работать в последний момент).

P.S. Cocoapods обновляется постоянно, исправляются ошибки, добавляются новые возможности (и новые ошибки). Если у вас что-то перестало работать (а такое случается), не поленитесь, пожалуйста, найти причину, и, если дело именно в cocoapods, дайте знать разработчикам.

Автор: pcholberg

Источник

Поделиться

* - обязательные к заполнению поля