Framework with dependencies
Let's say we have two frameworks CalcEngine and Core, and we need to include CalcEngine framework inside Core as dependency. There are multiple methods and some of them are described below.
Manual integration
There are multiple ways to add CalcEngine framework to a Core framework manually.
As source code
If we have code of both frameworks we can include the dependency framework directly to the code of the main framework. It can be included as gitsubmodule as well.
As xcframework
We can also add CalcEngine to the source code of Core by dragging CalcEngine.xcframework to the Frameworks and Libraries section in Core target settings.
As hidden dependency
Procedure for adding CalcEngine as hidden dependency of Core is same as adding is as xcframework. The only difference is that we cannot simply import CalcEngine. Instead, we need to use @implementationOnly import to hide CalcEngine from swiftinterface file and Objective-C headers.
Limitation
The Limitation of this approach is that we cannot use any types, classes or conform to protocols from CalcEngine in public types/methods/classes/protocols of Core framework. This is enforced by the compiler. Also, @testable import Core used in unit tests can behave unexpectedly.
@implementationOnly import is not officially supported by Apple!
More details in Framework with hidden dependenciesarticle.
CocoaPods
As dependency
We can add CalcEngine to Core.podspec file and define which versions we work with.
Pod::Spec.new do |s|
s.name = 'Core'
s.version = '1.0.0'
s.summary = 'Core framework used inside MyCompany'
s.description = 'Core framework used inside MyCompany'
s.homepage = 'https://mycompany.com'
s.license = { :type => 'MIT', :file => 'LICENCE' }
s.author = { 'MyCompany' => '[email protected]' }
s.source = { :http => 'https://mycompany/frameworks/core/#{s.version}/Core.zip'}
s.ios.deployment_target = '10.0'
s.ios.vendored_frameworks = 'Core.xcframework'
s.frameworks = 'UIKit'
s.dependency 'CalcEngine', '>= 0.1 < 0.3'
end
This states that Core depends on CalcEngine and can use any version between 0.1 and 0.3.
There's also possibility to use "optimistic version indicator" ~>, it's also recommended by CocoaPods.
Optimistic version indicator
It uses the last semantic version defined and allows updating of it but doesn't allow higher semantic version.
- ~> major.minor.patch → allow updating of patch version but don't allow minor version update
- ~> major.minor → allow patch and minor version update
Examples
- ~> 1.0.1 is equivalent to >= 1.0.1 combined with < 1.1
- ~> 1.0 will match 1.0, 1.0.1, 1.1, but will not 2.0
Developers can provide a different version of the framework, but it must be compatible with the version defined in Core.podspec, otherwise it will throw an error.
If the developer specifies pod CalcEngine, '1.0' in Podfile and in Core.podspec we have s.dependency CalcEngine, '~> 0.1', the developer will receive the following error.
As subspec
Another solution that is that we can create a "parent" framework that will have subspec frameworks defined.
If we have a framework that offers multiple frameworks that all together are one big solution but at the same time can be used separately we can define one "parent" framework that lists all others as subspec.
Pod::Spec.new do |s|
s.name = 'MyCompany'
s.subspec 'Core' do |core|
core.source_files = 'Core.xcframework'
core.dependency 'MyCompany/CalcEngine'
end
s.subspec 'CalcEngine' do |ce|
ce.source_files = 'CalcEngine.xcframework'
end
end
More details in Pod with child podsarticle.