У меня есть приложение (пусть его называют MyApp), написанное в Swift со следующими целями:
-
MyApp
: главная цель -
MyAppKit
: целевое построение рамки для кода, который используется совместно с приложением и его расширением (-ами), в основном с использованием API-интерфейса и обработки базы данных -
MyAppWidget
: вид виджета Today View (или что бы он ни называл сейчас), который использует структуруMyAppKit
.
Структура MyAppKit
привязана к каждой цели, которая использует ее, а именно MyApp
и MyAppWidget
. Введите Cocoapods: у меня была следующая структура Podfile:
platform :ios, '8.0'
use_frameworks!
target 'MyApp' do
# Mostly UI or convenience pods
pod 'Eureka', '~> 2.0.0-beta'
pod 'PKHUD', '~> 4.0'
pod '1PasswordExtension', '~> 1.8'
end
target 'MyAppKit' do
# Backend pods for networking, storage, etc.
pod 'Alamofire', '~> 4.0'
pod 'Fuzi', '~> 1.0'
pod 'KeychainAccess', '~> 3.0'
pod 'RealmSwift', '~> 2.0'
pod 'Result', '~> 3.0'
end
target 'MyAppWidget' do
# Added here event though the target only imports MyAppKit but it worked
pod 'RealmSwift', '~> 2.0'
end
Цель здесь заключалась в том, чтобы разоблачить только структуру MyAppKit
для других частей, а не для всех ее модулей (например, я не хочу иметь возможность import Alamofire
в основное приложение). Однако, начиная с Cocoapods 1.2.0 RCs, pod install
не удалась со следующей ошибкой: [!] The 'Pods-MyApp' target has frameworks with conflicting names: realm and realmswift.
, Он работал, потому что контейнеры были объявлены для расширения, но только встроены в хост-приложение (подробнее см. Эту проблему). Поэтому я удалил контейнеры из целевого объекта виджета, оставив мне только пустую target 'MyAppWidget'
.
В этой конфигурации pod install
выполняется нормально, но компиляция не выполняется на этапе компоновки для цели MyAppWidget
: ld: framework not found Realm for architecture x86_64
. Это можно устранить, явно добавив как Realm.framework
и RealmSwift.framework
в RealmSwift.framework
"Link Binary With Libraries" и следующий параметр сборки в целевом Pods-MyAppWidget.[debug/release].xcconfig
:
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Realm" "$PODS_CONFIGURATION_BUILD_DIR/RealmSwift"'
Тем не менее, всякий раз, когда я запускаю pod install
, настройки сборки, естественно, возвращаются, и мне нужно снова добавить настройки сборки.
Я вижу следующие решения:
- Добавьте
post_install
хук, добавляя эти настройки каждый раз, но он кажется "взломанным" и после нескольких ошибочных попыток, я не нашел ссылки на API и не знаю, как добавить эти параметры в целевой объектMyAppWidget
через скрипт. -
Измените подфайл на следующую структуру (или даже заверните ее в абстрактную цель):
[...] target 'MyAppKit' do # Backend pods for networking, storage, etc. pod 'Alamofire', '~> 4.0' pod 'Fuzi', '~> 1.0' pod 'KeychainAccess', '~> 3.0' pod 'RealmSwift', '~> 2.0' pod 'Result', '~> 3.0' target 'MyAppWidget' do inherit! :search_paths # Because else we get the "conflicting names" error end end
Который кажется логичным для меня в смысле "виджет должен знать, где искать во время компоновки, но не нуждается в контейнерах как таковых",
но это не добавляет вышеупомянутые настройки сборки (я, вероятно, неправильно(edit: он работает, но не с абстрактной мишенью). Эта идея пришла ко мне, потому что в более старых версиях CocoaPods решение, по- видимому, должно было добавить:search_paths
inheritance)link_with
, который теперь устарел. - Expose Realm также находится в целевом
MyApp
, однако это противоречит моей цели - не иметь доступ к коду "backend" в главном коде (это может быть чисто эстетично?).
Итак, вот мой вопрос: какой лучший способ интегрировать контейнеры в инфраструктуру, разделяемые между основным приложением и расширением, все еще находясь в состоянии скомпилировать, не настраивая и не добавляя вручную?
Приветствия и спасибо заранее!
РЕДАКТИРОВАТЬ
Следуя замечанию Приента, я изучил возможности абстракции и наследования. Основные проблемы, которые я сейчас раскрыл, на самом деле многообразны:
- Раньше он работал перед Cocoapods 1.2.0, потому что контейнеры, объявленные под целью виджета, были встроены в хост-приложение, но все еще связаны с виджетами. Нет, он просто отказывается иметь стручки с одним и тем же именем для разных целей в соотношении "главное против расширения"
- Использование абстрактных целей недостаточно, потому что цели не могут наследовать только пути поиска (
inherit! :search_paths
) от абстрактной цели. - Пути поиска могут быть унаследованы от реальной цели, такой как
MyAppKit
, но это предоставляет все этиMyApp
кодаMyApp
(чего я хочу избежать), и все еще существует проблема связывания структуры Realm (поскольку на самом деле виджет использует мельчайший бит геттер и, следовательно, нуждается в нем).
Использование этой последней опции и ручная привязка Realm.framework работает, но субоптимально относительно моих намерений и того, что использовалось для работы. Некоторые из этих вопросов, как представляется, ошибка в соответствии с различными вопросами на GitHub Cocoapods. Я добавил свою собственную проблему и обновляю, когда у меня есть новости.