Can App Clip be used in an iOS Cocoapods project? - ios

Our App was created in 2018 mid using Swift 4, and other 3rd party depended with Cocoapods.
I add one Clip target, the project structure is different from that given by the download link under session. Run this target, here are the crash errors:
Reason: image not found
dyld: Library not loaded: #rpath/Alamofire.framework/Alamofire
Referenced from: /private/var/containers/Bundle/Application/57185773-B735-4EE5-BB51-790DF004A85B/kt_iOS_Clip.app/kt_iOS_Clip
Reason: image not found
dyld: launch, loading dependent libraries
DYLD_LIBRARY_PATH=/usr/lib/system/introspection
DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib:/Developer/Library/PrivateFrameworks/GPUTools.framework/libglInterpose.dylib:/usr/lib/libMTLCapture.dylib
Here is Podfile:
platform :ios, '10.0'
inhibit_all_warnings!
target '<Main App>' do
use_frameworks!
pod 'SnapKit' , '4.2.0'
pod 'Alamofire' , '4.7.3'
......
target '<Main App>Tests' do
inherit! :search_paths
end
swift_41_pod_targets = ['Spring','PKHUD', 'FSPagerView', 'SQLite.swift','FaveButton']
post_install do | installer |
installer.pods_project.targets.each do |target|
if target.name == 'Cache'
target.build_configurations.each do |config|
level = '-Osize'
config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] = level
puts "Set #{target.name} #{config.name} to Optimization Level #{level}"
end
end
if swift_41_pod_targets.include?(target.name)
target.build_configurations.each do |config|
config.build_settings['SWIFT_VERSION'] = '4.1'
end
end
end
end
target '<Main App>UITests' do
inherit! :search_paths
end
end

As other answers mentioned, separate app clip target and use_modular_headers! worked for me
platform :ios, '13.0'
target 'MainAppTarget' do
use_frameworks!
pod 'Firebase/Analytics'
pod 'Firebase/RemoteConfig'
target 'MainAppTargetTests' do
inherit! :search_paths
end
end
target 'AppClipTarget' do
use_modular_headers!
pod 'Firebase/Analytics'
target 'AppClipTargetTests' do
inherit! :search_paths
end
target 'AppClipTargetUITests' do
end
end

I fixed this problem by adding another target in my podfile which pointed to the AppClip target
Ref: https://www.natashatherobot.com/cocoapods-installing-same-pod-multiple-targets/

YES, but NO at present (2020.7.15).
igor-makarov had commit an app clip support to master, now just wait for next CocoaPods release.
https://github.com/CocoaPods/CocoaPods/commit/3a5deed0adfa306307027753898cca5e23be14bd

I think the right way to do it is having another target (in my case I placed it outside the main one, because I only want a few pods).
However, Cocoapods needs to update something to export/setup everything right. Since App Clips were introduced recently, Cocoapods hasn't released a new stable version with the fix (https://github.com/CocoaPods/CocoaPods/pull/9882). So we just have to wait a bit, I guess. In the meantime, you can add the Embed Pods Frameworks manually and it will work fine.
Ref: https://developer.apple.com/forums/thread/652683?login=true

What worked for me is doing:
sudo gem install cocoapods --pre
Cocoapods latest stable release at the time of this post was not supporting the app clip target with cocoaPods.

Related

Cocoapods with multiple projects: Firebase causes "Class XXX is implemented in both (...)" warning

I'm currently working on a Swift project where the workspace contains multiple projects (ACM...) due to company decision.
When adding Firebase with Cocoapods, I need it in two of the projects (in 'myapp' and 'ACMLoyalty'). So my .podfile looks like this:
workspace 'myapp.xcworkspace'
platform :ios, '12.0'
use_frameworks!
def shared_pods
source 'https://github.com/CocoaPods/Specs.git'
pod 'Nuke', '9.2.3'
pod 'Alamofire', '~> 4.9.1'
pod 'DeepDiff', '2.3.1'
end
def firebase_pods
pod 'Firebase/Analytics', '7.4.0'
pod 'Firebase/Crashlytics', '7.4.0'
pod 'Firebase', '7.4.0'
end
def appcenter_pods
pod 'AppCenter', '4.1.0'
pod 'AppCenter/Distribute', '4.1.0'
end
project 'myapp.xcodeproj'
project 'ACMCore/ACMCore.xcodeproj'
project 'ACMData/ACMData.xcodeproj'
project 'ACMLoyalty/ACMLoyalty.xcodeproj'
project 'ACMMVVM/ACMMVVM.xcodeproj'
project 'ACMNetwork/ACMNetwork.xcodeproj'
project 'ACMShared/ACMShared.xcodeproj'
target :myapp do
project 'myapp.xcodeproj'
shared_pods
firebase_pods
appcenter_pods
end
target :ACMCore do
project 'ACMCore/ACMCore.xcodeproj'
shared_pods
end
target :ACMData do
project 'ACMData/ACMData.xcodeproj'
shared_pods
end
target :ACMLoyalty do
use_frameworks! :linkage => :dynamic
project 'ACMLoyalty/ACMLoyalty.xcodeproj'
shared_pods
firebase_pods
target 'ACMLoyaltyTests' do
inherit! :search_paths
shared_pods
firebase_pods
end
target 'ACMLoyaltyTestHost' do
inherit! :search_paths
shared_pods
firebase_pods
end
end
target :ACMMVVM do
project 'ACMMVVM/ACMMVVM.xcodeproj'
shared_pods
target 'ACMMVVMTests' do
inherit! :search_paths
shared_pods
end
end
target :ACMNetwork do
project 'ACMNetwork/ACMNetwork.xcodeproj'
shared_pods
target 'ACMNetworkTests' do
inherit! :search_paths
shared_pods
end
end
target :ACMShared do
project 'ACMShared/ACMShared.xcodeproj'
shared_pods
target 'ACMSharedTests' do
inherit! :search_paths
shared_pods
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if Gem::Version.new('9.0') > Gem::Version.new(config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'])
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
end
end
end
end
Problem:
During run-time I get following warnings in the console:
objc[2946]: Class FIRAnalyticsConnector is implemented in both /private/var/containers/Bundle/Application/05B31227-083E-42A7-9E27-DB7924A754B9/myapp.app/Frameworks/ACMLoyalty.framework/ACMLoyalty (0x107c4d1b8) and /private/var/containers/Bundle/Application/05B31227-083E-42A7-9E27-DB7924A754B9/myapp.app/myapp (0x104217298). One of the two will be used. Which one is undefined.
This is just one line as sample, but there are a lot of other Firebase classes listed with the same description.
After some research I know, that the problem is, that Firebase is a static library and will be simply copied to the specific target which causes this issue. With the other libraries (dynamic) this problem doesn't occur.
Does anybody have a solution for my problem?
Edit: Answer #mbi
I already tried a solution with abstract_target.
Please find my .podfile for this attempt:
# Uncomment the next line to define a global platform for your project
workspace 'myapp.xcworkspace'
platform :ios, '12.0'
use_frameworks!
project 'myapp.xcodeproj'
project 'ACMCore/ACMCore.xcodeproj'
project 'ACMData/ACMData.xcodeproj'
project 'ACMLoyalty/ACMLoyalty.xcodeproj'
project 'ACMMVVM/ACMMVVM.xcodeproj'
project 'ACMNetwork/ACMNetwork.xcodeproj'
project 'ACMShared/ACMShared.xcodeproj'
abstract_target 'myapp-app' do
source 'https://github.com/CocoaPods/Specs.git'
pod 'Nuke', '9.2.3'
pod 'Alamofire', '~> 4.9.1'
pod 'DeepDiff', '2.3.1'
pod 'Firebase/Analytics', '7.4.0'
pod 'Firebase/Crashlytics', '7.4.0'
pod 'Firebase', '7.4.0'
def appcenter_pods
pod 'AppCenter', '4.1.0'
pod 'AppCenter/Distribute', '4.1.0'
end
target :myapp do
project 'myapp.xcodeproj'
appcenter_pods
end
target :ACMCore do
project 'ACMCore/ACMCore.xcodeproj'
end
target :ACMData do
project 'ACMData/ACMData.xcodeproj'
end
target :ACMLoyalty do
project 'ACMLoyalty/ACMLoyalty.xcodeproj'
target 'ACMLoyaltyTests' do
end
target 'ACMLoyaltyTestHost' do
end
end
target :ACMMVVM do
project 'ACMMVVM/ACMMVVM.xcodeproj'
target 'ACMMVVMTests' do
end
end
target :ACMNetwork do
project 'ACMNetwork/ACMNetwork.xcodeproj'
target 'ACMNetworkTests' do
end
end
target :ACMShared do
project 'ACMShared/ACMShared.xcodeproj'
target 'ACMSharedTests' do
end
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if Gem::Version.new('9.0') > Gem::Version.new(config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'])
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
end
end
end
end
The problem is, with this solution I have even more warning, because Firebase is built in ALL projects and conflicts.
EDIT2: With the answer of #arturdev I got it working without the ... implemented in both... warning with following podfile:
# Uncomment the next line to define a global platform for your project
workspace 'myapp.xcworkspace'
platform :ios, '12.0'
use_frameworks!
project 'myapp.xcodeproj'
project 'ACMCore/ACMCore.xcodeproj'
project 'ACMData/ACMData.xcodeproj'
project 'ACMLoyalty/ACMLoyalty.xcodeproj'
project 'ACMMVVM/ACMMVVM.xcodeproj'
project 'ACMNetwork/ACMNetwork.xcodeproj'
project 'ACMShared/ACMShared.xcodeproj'
abstract_target 'myapp-app' do
source 'https://github.com/CocoaPods/Specs.git'
pod 'Nuke', '9.2.3'
pod 'Alamofire', '~> 4.9.1'
pod 'DeepDiff', '2.3.1'
def firebase_pods
pod 'Firebase/Analytics', '7.4.0'
pod 'Firebase/Crashlytics', '7.4.0'
pod 'Firebase', '7.4.0'
end
def appcenter_pods
pod 'AppCenter', '4.1.0'
pod 'AppCenter/Distribute', '4.1.0'
end
target :myapp do
project 'myapp.xcodeproj'
firebase_pods
appcenter_pods
target 'myappTests' do
end
end
target :ACMCore do
project 'ACMCore/ACMCore.xcodeproj'
target 'ACMCoreTests' do
firebase_pods
end
end
target :ACMData do
project 'ACMData/ACMData.xcodeproj'
target 'ACMDataTests' do
firebase_pods
end
end
target :ACMLoyalty do
project 'ACMLoyalty/ACMLoyalty.xcodeproj'
firebase_pods
target 'ACMLoyaltyTests' do
end
target 'ACMLoyaltyTestHost' do
end
end
target :ACMMVVM do
project 'ACMMVVM/ACMMVVM.xcodeproj'
target 'ACMMVVMTests' do
end
end
target :ACMNetwork do
project 'ACMNetwork/ACMNetwork.xcodeproj'
target 'ACMNetworkTests' do
end
end
target :ACMShared do
project 'ACMShared/ACMShared.xcodeproj'
target 'ACMSharedTests' do
end
end
end
PROJECT_ROOT_DIR = File.dirname(File.expand_path(__FILE__))
PODS_DIR = File.join(PROJECT_ROOT_DIR, 'Pods')
PODS_TARGET_SUPPORT_FILES_DIR = File.join(PODS_DIR, 'Target Support Files')
post_install do |installer|
## For more information: https://stackoverflow.com/questions/65904011/cocoapods-with-multiple-projects-firebase-causes-class-xxx-is-implemented-in-b
remove_static_framework_duplicate_linkage({
'ACMLoyalty' => ['FBLPromises', 'FIRAnalyticsConnector', 'FirebaseAnalytics', 'FirebaseCore', 'FirebaseCoreDiagnostics', 'FirebaseCrashlytics', 'FirebaseInstallations', 'GoogleAppMeasurement', 'GoogleDataTransport', 'GoogleUtilities']
})
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
#config.build_settings['LD_NO_PIE'] = 'NO'
if Gem::Version.new('9.0') > Gem::Version.new(config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'])
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
end
end
end
end
# CocoaPods provides the abstract_target mechanism for sharing dependencies between distinct targets.
# However, due to the complexity of our project and use of shared frameworks, we cannot simply bundle everything under
# a single abstract_target. Using a pod in a shared framework target and an app target will cause CocoaPods to generate
# a build configuration that links the pod's frameworks with both targets. This is not an issue with dynamic frameworks,
# as the linker is smart enough to avoid duplicate linkage at runtime. Yet for static frameworks the linkage happens at
# build time, thus when the shared framework target and app target are combined to form an executable, the static
# framework will reside within multiple distinct address spaces. The end result is duplicated symbols, and global
# variables that are confined to each target's address space, i.e not truly global within the app's address space.
#
# Previously we avoided this by linking the static framework with a single target using an abstract_target, and then
# provided a shim to expose their interfaces to other targets. The new approach implemented here removes the need for
# shim by modifying the build configuration generated by CocoaPods to restrict linkage to a single target.
def remove_static_framework_duplicate_linkage(static_framework_pods)
puts "Removing duplicate linkage of static frameworks"
Dir.glob(File.join(PODS_TARGET_SUPPORT_FILES_DIR, "Pods-*")).each do |path|
pod_target = path.split('-', -1).last
static_framework_pods.each do |target, pods|
next if pod_target == target
frameworks = pods.map { |pod| identify_frameworks(pod) }.flatten
Dir.glob(File.join(path, "*.xcconfig")).each do |xcconfig|
lines = File.readlines(xcconfig)
if other_ldflags_index = lines.find_index { |l| l.start_with?('OTHER_LDFLAGS') }
other_ldflags = lines[other_ldflags_index]
frameworks.each do |framework|
other_ldflags.gsub!("-framework \"#{framework}\"", '')
end
File.open(xcconfig, 'w') do |fd|
fd.write(lines.join)
end
end
end
end
end
end
def identify_frameworks(pod)
frameworks = Dir.glob(File.join(PODS_DIR, pod, "**/*.framework")).map { |path| File.basename(path) }
if frameworks.any?
return frameworks.map { |f| f.split('.framework').first }
end
return pod
end
Some of the pod dependencies are being compiled as a static library and not dynamic (f.e. Firebase and other Google libs).
A static framework can't be linked more than once (f.e. in a framework target and in a main target which also links the framework above), because the linkage of static frameworks happens during build-time, yet for the dynamic frameworks the linkage happens on runtime and the linker is smart enough to avoid duplications.
Therefore you need to write a script in your podfile to remove static library linkages.
A dirty example:
post_install do |installer|
remove_static_framework_duplicate_linkage({
'FrameworkTarget1' => ['Firebase', 'FirebaseAnalytics', 'FirebaseCore', 'FirebaseCoreDiagnostics', 'FirebaseCoreDiagnosticsInterop', 'FirebaseInstanceID', 'FirebaseInstallations', 'GoogleAppMeasurement', 'GoogleDataTransport', 'GoogleDataTransportCCTSupport', 'GoogleUtilities'],
'FrameworkTarget2' => ['GoogleMaps', 'GooglePlaces'],
})
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['LD_NO_PIE'] = 'NO'
config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET'
end
end
end
# CocoaPods provides the abstract_target mechanism for sharing dependencies between distinct targets.
# However, due to the complexity of our project and use of shared frameworks, we cannot simply bundle everything under
# a single abstract_target. Using a pod in a shared framework target and an app target will cause CocoaPods to generate
# a build configuration that links the pod's frameworks with both targets. This is not an issue with dynamic frameworks,
# as the linker is smart enough to avoid duplicate linkage at runtime. Yet for static frameworks the linkage happens at
# build time, thus when the shared framework target and app target are combined to form an executable, the static
# framework will reside within multiple distinct address spaces. The end result is duplicated symbols, and global
# variables that are confined to each target's address space, i.e not truly global within the app's address space.
#
# Previously we avoided this by linking the static framework with a single target using an abstract_target, and then
# provided a shim to expose their interfaces to other targets. The new approach implemented here removes the need for
# shim by modifying the build configuration generated by CocoaPods to restrict linkage to a single target.
def remove_static_framework_duplicate_linkage(static_framework_pods)
puts "Removing duplicate linkage of static frameworks"
Dir.glob(File.join(PODS_TARGET_SUPPORT_FILES_DIR, "Pods-*")).each do |path|
pod_target = path.split('-', -1).last
static_framework_pods.each do |target, pods|
next if pod_target == target
frameworks = pods.map { |pod| identify_frameworks(pod) }.flatten
Dir.glob(File.join(path, "*.xcconfig")).each do |xcconfig|
lines = File.readlines(xcconfig)
if other_ldflags_index = lines.find_index { |l| l.start_with?('OTHER_LDFLAGS') }
other_ldflags = lines[other_ldflags_index]
frameworks.each do |framework|
other_ldflags.gsub!("-framework \"#{framework}\"", '')
end
File.open(xcconfig, 'w') do |fd|
fd.write(lines.join)
end
end
end
end
end
end
def identify_frameworks(pod)
frameworks = Dir.glob(File.join(PODS_DIR, pod, "**/*.framework")).map { |path| File.basename(path) }
if frameworks.any?
return frameworks.map { |f| f.split('.framework').first }
end
return pod
end
The error Class XYZ is implemented in both ... indicates that the same class is beeing compiled and linked into more than one built product. You are making things more complex than they need to be.
I'm really having a hard time to figure out by looking at the given Podfile what your actually trying to achieve. Obviously there a few things that could be improved but that heavily depends on what the requirements are.
For example you should read about and use the concept of abstract_target and nesting targets in a Podfile. This gives you the possibility to describe dependencies just one time and inherit them to the nested targets. See https://guides.cocoapods.org/using/the-podfile.html
Furthermore you have to keep in mind that Cocoapods is applying something called dedublication which basically means no matter how often you specify a dependency in your Podfile it tries to squash them into as least targets as possible in the generated Pods project. So to me the many statements of the very same dependencies such as share_pods in your Podfile seem some kind of wrong.
And in my opinion you are using inheritance in a weird way. For example you limit inheritance to exclude parent's deps just to add them again in the next line. Example:
target :ACMMVVM do
project 'ACMMVVM/ACMMVVM.xcodeproj'
shared_pods # <-- dependency here
target 'ACMMVVMTests' do
inherit! :search_paths # <-- excluded here
shared_pods # <-- added again here
end
end
As of my experience in most cases nested test targets don't need the dependencies so inheriting just search paths as you do is just fine. But only you know whether this particular test target really depends on share_pods or not.
I'm pretty sure once you sort out your actual requirements and rewrite the Podfile to a nested structure of abstract and non-abstract targets there is a very high chance that your problem goes away.

No such Module Firebase

I have a react-native project and I have to link my xCode project with firebase. Even though I used CocoaPod and manual ways I am getting the error
"No such module as firebase.h".
I have followed all the steps correctly.
Uncomment the next line to define a global platform for your project
platform :ios, '9.0'
target 'App' do
# Uncomment the next line if you're using Swift or would like to use
dynamic frameworks
# use_frameworks!
# Pods for App
target 'App-tvOSTests' do
inherit! :search_paths
# Pods for testing
end
target 'AppTests' do
inherit! :search_paths
# Pods for testing
end
pod 'Google-Mobile-Ads-SDK'
pod 'Firebase/Core', '~> 5.6.0'
pod 'GoogleIDFASupport'
end
target 'App-tvOS' do
# Uncomment the next line if you're using Swift or would like to use
dynamic frameworks
# use_frameworks!
# Pods for App-tvOS
end
I also faced this problem. I was using react-native-firebase package. Please try following their official docs . I would rate their documentation 10/10 as they've explained every possible scenario a developer would face during integration.
Just change value with deployment target of your app.
platform :ios, 'value'
inhibit_all_warnings!
def sharedpods
pod 'Google-Mobile-Ads-SDK'
pod 'Firebase/Core', '~> 5.6.0'
pod 'GoogleIDFASupport'
end
target 'AppTests’ do
use_frameworks!
sharedpods
end
target 'App-tvOSTests’ do
use_frameworks!
sharedpods
end
target 'App-tvOS’ do
use_frameworks!
sharedpods
end
#post_install do |installer|
# installer.pods_project.targets.each do |target|
# puts "#{target.name}"
# end
#end

The bundle “MyProjectUITests” couldn’t be loaded because it is damaged or missing necessary resources. Try reinstalling the bundle

I'm willing to add unit and UI tests to my app.
I first configured unit tests with success, I tried to do the same with UI tests. Here is my Podfile, after adding a new UI Testing Bundle target :
platform :ios, '8.0'
use_frameworks!
inhibit_all_warnings!
def shared_pods
pod 'Bolts'
pod 'Branch'
pod 'FBSDKCoreKit'
pod 'FBSDKLoginKit'
pod 'FBSDKShareKit'
pod 'GoogleAnalytics'
pod 'GooglePlaces'
pod 'Parse'
pod 'Toast-Swift'
end
target 'MyTarget' do
shared_pods
end
target 'MyTargetUITests' do
shared_pods
end
target 'MyTargetUnitTests' do
shared_pods
end
However, when I try to run the automatically created MyProjectUITests test case, which only contains the basic setup and without even a #testable import MyProject:
import XCTest
class MyProjectUITests: XCTestCase {
override func setUp() {
continueAfterFailure = false
XCUIApplication().launch()
}
}
I'm getting this error:
Running tests...
The bundle “MyProjectUITests” couldn’t be loaded because it is damaged or missing necessary resources. Try reinstalling the bundle.
(dlopen_preflight(/var/containers/Bundle/Application/5A1FE39F-E675-4A47-9BF4-FBCDB96F5821/MyProjectUITests-Runner.app/PlugIns/MyProjectUITests.xctest/MyProjectUITests): Library not loaded: #rpath/libswiftSwiftOnoneSupport.dylib
Referenced from: /private/var/containers/Bundle/Application/5A1FE39F-E675-4A47-9BF4-FBCDB96F5821/MyProjectUITests-Runner.app/PlugIns/MyProjectUITests.xctest/Frameworks/Toast_Swift.framework/Toast_Swift
Reason: image not found)
What is wrong? Thanks for your help.
EDIT : for information, it works fine when I remove that Toast_swift pod from my UI test target and let it only in my app and unit test targets.
Check out this issue on the cocoapods github issue tracker.
I'm still a little confused as to why this became a problem but the setting the ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES to YES using this script fixed the issue for me.
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
# This works around a unit test issue introduced in Xcode 10.
# We only apply it to the Debug configuration to avoid bloating the app size
if config.name == "Debug" && defined?(target.product_type) && target.product_type == "com.apple.product-type.framework"
config.build_settings['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = "YES"
end
end
end
end
Try adding inherit! :search_paths
and also changing ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES in post_install
use_frameworks!
def shared_pods
pod 'SomePod'
end
target 'App_name' do
shared_pods
end
target 'App_nameTests' do
inherit! :search_paths
shared_pods
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = 'YES'
end
end
end
I too faced this issue and none of the other suggestions worked.
After a while I found out that specifically using print() anywhere in your code will somehow force libswiftSwiftOnoneSupport.dylib to be loaded and the issue will go away.
I'm using Xcode 10.1, Swift 4.2 and the pod that was giving me this issue was Nimble.
Hope this helps!

Can't find the right way to build my own framework target with my main app target

I decided to split my main project in two parts to reuse code, in a iOS widget.
So I created a new target file in my xcworkspace (cocoa touch framework).
Both targets have some pod dependencies in common and I can't figure the way right way to build.
First try:
In podfile, I've specified needed pods for both targets, but when building, I've multiple errors
Class Foo is implemented in both MyApp and MyFramework. One of the two will be used. Which one is undefined.
Second try:
Then I tried put framework target inside main app target (like we do usually with a test target)
target 'MyApp' do
main_pods
app_pods
target 'MyFramework' do
inherit! :search_paths
target 'MyFrameworkTests' do
inherit! :search_paths
testing_pods
end
end
end
But then the framework won't build as it didn't found dependencies
Example:
No such module Firebase
Note:
To build my main target, I've to build the framework target first, otherwise it's doesn't find 'MyFramework' module. No way to build both when I build the main target ?
I also have an app where I created a framework in a separate project but the same workspace. I use pods to get all external libraries, and embed my own framework in app's targets by adding it to Embedded Binaries in Xcode. My Podfile looks like this:
workspace 'MyApp'
abstract_target 'BasePods' do
use_frameworks!
pod 'Alamofire', '~> 4.4'
pod 'PromiseKit', '~> 4.1'
project '../MyAppProject/MyApp/MyApp.xcodeproj'
target 'MyApp'
target 'MyAppDevelopment'
end
target 'MyAppCore' do
use_frameworks!
pod 'Alamofire', '~> 4.4'
pod 'PromiseKit', '~> 4.1'
project '../MyAppProject/MyAppCore/MyAppCore.xcodeproj'
target 'MyAppCoreTests' do
inherit! :search_paths
end
end
What happens here I create two separate pod targets - one for the app, another one for the framework. I split them because they reside in different directories.
Got it, I had static libraries framework dependencies and the iOS linker does not support static library dependencies for dynamic libraries.
CF issue: https://github.com/CocoaPods/CocoaPods/issues/7126
I've solved it via Podfile by a workaround posted in the above issue:
post_install do |installer|
sharedLibrary = installer.aggregate_targets.find { |aggregate_target| aggregate_target.name == 'Pods-SampleFramework' }
installer.aggregate_targets.each do |aggregate_target|
if aggregate_target.name == 'Pods-SampleApp'
aggregate_target.xcconfigs.each do |config_name, config_file|
sharedLibraryPodTargets = sharedLibrary.pod_targets
aggregate_target.pod_targets.select { |pod_target| sharedLibraryPodTargets.include?(pod_target) }.each do |pod_target|
pod_target.specs.each do |spec|
frameworkPaths = unless spec.attributes_hash['ios'].nil? then spec.attributes_hash['ios']['vendored_frameworks'] else spec.attributes_hash['vendored_frameworks'] end || Set.new
frameworkNames = Array(frameworkPaths).map(&:to_s).map do |filename|
extension = File.extname filename
File.basename filename, extension
end
frameworkNames.each do |name|
puts "Removing #{name} from OTHER_LDFLAGS"
config_file.frameworks.delete(name)
end
end
end
xcconfig_path = aggregate_target.xcconfig_path(config_name)
config_file.save_as(xcconfig_path)
end
end
end
end

CocoaPods - Unable to find a specification for `GoogleMaps`

I'm new to iOS, i already have Alamofire and MarqueeLabel on my Podfile and now trying to add GoogleMaps, it keeps showing this message,
[!] Unable to find a specification for `GoogleMaps`
My Podfile looks like this
# Uncomment the next line to define a global platform for your project
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
target 'Migapixel' do
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
pod 'GoogleMaps'
pod 'Alamofire',
:git => 'https://github.com/Alamofire/Alamofire.git',
:branch => 'master',
:tag => '4.0.0'
pod 'MarqueeLabel/Swift',
:git => 'https://github.com/cbpowell/MarqueeLabel.git'
# Pods for Migapixel
post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = 'NO' end end end
target 'MigapixelTests' do
inherit! :search_paths
end
target 'MigapixelUITests' do
inherit! :search_paths
# Pods for testing
end
end
i even tried this
pod 'GoogleMaps',
:git => 'https://github.com/CocoaPods/Specs.git'
What am i doing wrong?
Try removing source 'https://github.com/CocoaPods/Specs.git' and moving use_frameworks! out of the target block. Moreover you don't need to manually set the git path for both Alamofire and MarqueeLabel.
Try this:
platform :ios, '9.0'
use_frameworks!
target 'Migapixel' do
pod 'GoogleMaps'
pod 'Alamofire'
pod 'MarqueeLabel/Swift'
# Pods for Migapixel
end
post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = 'NO' end end end
target 'MigapixelTests' do
inherit! :search_paths
end
target 'MigapixelUITests' do
inherit! :search_paths
# Pods for testing
end
Edit:
It seems that there's something wrong with your local repo.
Try cleaning and reinstalling:
pod repo remove master
pod setup
i resolved the issue like that with these step:
open terminal.
go to your project path.
type:
pod repo update
install pod again.
After trying many things Here is the fix!!
Imp: Make sure that you have these lines in your PodFile
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
pod 'GoogleMaps'
end
If the above is fine then you need to update the pods:
try the following steps:
Open a new terminal and run the following command in a temp directory.
pod try GoogleMaps
keep patience! It will take some time but will update the pod.
Now try to install the pod in ur project again. It should work.Else try to run the following commands in the project dir:
pod repo update
try again.
Comment in the case of any issue!!
Go to your project directory and delete pods folder and .lock file then run
pod repo update
it helps for me.

Resources