Использование Cocoapods в расширении приложения с помощью фреймворка

у меня есть приложение (назовем его MyApp), написанное в Swift со следующими целями:

  • MyApp : основной элемент
  • MyAppKit : целевое построение фреймворка для кода, который совместно используется между приложением и его расширением(ов), в основном бэкэнд API и обработка базы данных
  • MyAppWidget : виджет просмотра сегодня (или как бы он ни назывался сейчас), который использует MyAppKit основы.

на MyAppKit основа связана на каждую цель, которая его использует, а именно MyApp и MyAppWidget. Введите Cocoapods: раньше у меня была следующая структура Подфайлов:

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 в раздел "связать двоичный файл с библиотеками"и следующую настройку сборки в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
    

    что кажется мне логичным в смысле "виджет должен знать, где искать во время связывания, но не нуждается в стручках как таковых"но это не добавляет вышеупомянутых настроек сборки (я, вероятно, неправильно понимаю :search_paths наследование) (edit: он действительно работает, но не с абстрактной целью). Эта идея пришла ко мне, потому что в более старых версиях CocoaPods решение видимо, чтобы добавить link_with, который теперь устарел.

  • Expose Realm также в MyApp цель, однако это противоречит моей цели не имея доступа к "серверной" в основном коде (это может быть чисто эстетическим?).

Итак, вот мой вопрос : каков наилучший способ интегрировать стручки в рамках, разделяемых между основным приложением и расширением, все еще будучи в состоянии компилировать, без настройки вокруг и вручную добавлять вещи?

ура и спасибо заранее!


редактировать

после Prientus' я исследовал возможности абстракции и наследования. Основные проблемы, которые я сейчас обнаружил, на самом деле многообразны:

  • он работал до Cocoapods 1.2.0, потому что стручки, объявленные под целью виджета, были встроены в хост-приложение, но все еще связаны с виджетом. Нет, это просто отказывается иметь стручки с одинаковым именем для разных целей в отношениях "main vs extension"
  • использование абстрактных целей недостаточно, поскольку цели не могут наследовать только пути поиска (inherit! :search_paths) от абстрактной цели.
  • пути поиска могут быть унаследованы от реальной цели, такой как MyAppKit, но это подвергает все эти стручки MyAppкод (которого я хочу избежать), и все еще есть проблема связывания Realm framework (потому что на самом деле виджет использует крошечный бит геттера и, следовательно, нуждается в нем).

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

3 ответов


Итак, что дает :

  • моя озабоченность "разделением стручков между целями" абсурдна, потому что вы все еще можете импортировать их в любом месте.
  • проблема "вы должны вручную связать" исправлена простым import RealmSwift заявление.

таким образом, фиксированный и рабочий Подфайл:

platform :ios, '8.0'
use_frameworks!

target 'MyApp' do
    pod 'Eureka', '~> 2.0.0-beta'
    pod 'PKHUD', '~> 4.0'
    pod '1PasswordExtension', '~> 1.8'
end

target 'MyAppKit' do
    pod 'Fuzi', '~> 1.0'
    pod 'RealmSwift', '~> 2.0'
    pod 'Alamofire', '~> 4.0'
    pod 'KeychainAccess', '~> 3.0'
    pod 'Result', '~> 3.0'

    target 'MyAppWidget' do
        inherit! :search_paths
    end
end

и это все. Я бы сказал, что старое поведение было более очевидным и не требовало чтения "целевого наследования подфайла". Я многому научился. хотя. Ура!


Я тебя не знаю. Но для меня совершенно законно и разумно иметь расширение, а хост-приложение содержит все модули, которые определяет фреймворк. И вот что я имею в виду:--4-->

def shared_pods
    pod 'Alamofire'
end

target 'Framework' do
    shared_pods
end

target 'Host' do
    shared_pods
    // Some other pods
end

target 'Extension' do
    shared_pods
end

Я знаю, что вы беспокоитесь, но если вы думаете об этом, все эти сторонние фреймворки, которые вы используете, все они имеют зависимости. Вам не нужно беспокоиться о них, потому что Cocoapods заботится о них за вас. Если вы хотите использовать это, вам нужно будет поместить локальную запись pod в список.

target 'Host' do
    pod Framework, :path => '../Framework'
end

но тогда вы должны поддерживать .


Это пример профиля проекта swift-3.0.

platform :ios, '8.0'

def import_public_pods

  pod 'SwiftyJSON'

end


target 'Demo' do
  use_frameworks!

  # Pods for Demo
  import_public_pods 
  pod 'Fabric'
  pod 'Crashlytics'

  target 'DemoTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'DemoUITests' do
    inherit! :search_paths
    # Pods for testing
  end

end


target 'DemoKit' do
  use_frameworks!

  # Pods for DemoKit
  import_public_pods
  pod 'RealmSwift'

  target 'DemoKitTests' do
    inherit! :search_paths
    # Pods for testing
  end

end