Cocoa pods interdependent dependencies - ios

I noticed while looking into my CI logs that one framework is compiled two times and after digging into the issue I noticed one dependency of the main project is also part of another pod dependency
Now I am looking into ways to make sure dependency(A) only compiles 1 time only
What could be the possible solution for this?

Try to remove pod A as POD B has the POD A dependency you can still access POD A library. We usually add our pod configuration when there is a mismatch of the version with our iOS Version or we want a specific version for our app and other pod dependency has different version, In that case we add our pod configuration for specific library with version.
For example In one my project there was a submodule which was also using the pod GoogleMLkit. But due to of limitation of iOS Version there was a compile time issue in order to use the same google library. At that time i had to enter pod in my main project with the version that i needed that is compaitable with my project.

if you want to check the dependency of your pod you have to move to pod folder and search *.podspec file in this file you would have something like this.
s.dependency 'packageName', '~> version'

Related

CocoaPods - A custom dynamic framework - cannot get the latest version of frameworks

My project in Xcode consist of static frameworks and one custom dynamic framework. This dynamic framework includes some other static frameworks.
When I try to compile the custom dynamic framework itself, everything is fine. I was able to force to install latest version of frameworks (Alamofire, Realm, etc..) by forcing the pod definition file
platform :ios, '9.0'
But when I compile my project even when I use the above line, I am getting the old frameworks.
When I try to force the pods for a explicit version,
pod 'Alamofire', '~> 4.4.0'
getting the version 3.5.1.
Is there any other explicit setting to force CocoaPods to be more accurate in versions?
Originally the project for the dynamic framework was made for the Swift version 2.3, which is actually requiring the version of Alamofire 3.5.1.
Any help will be appreciated.
Maybe try the following in your podfile:
pod 'Alamofire', :git => 'https://github.com/Alamofire/Alamofire.git', :tag => '4.4.0'
That will bypass your local spec repo and get straight from git.
Which version of CocoaPods you have currently installed on your machine? Which version was used to originally establish Pods in project? I've spotted an issue when I updated CocoaPods, that pod update hasn't been working properly, and removing just Podfile.lock and Pods/ directory wasn't sufficient to make things right.
That said I would do the following:
update CocoaPods to newest version
pod repo update for newest Pod specs
pod deintegrate to completely remove Pods from project
pod install to re-create Pods in the project
The solution is kinda tricky. I haven't realise in the beginning that the pods under a dynamic framework cannot actually be executed directly from top project and there is a configuration JSON file, which actually is managing the pods under the dynamic framework.
So the pod versions were actually hardcoded there.

Using a CocoaPod dependency while developing a CocoaPod

I'm creating a CocoaPod, say MyPod, which depends on another Cocoapod, say RxSwift.
So I have this in MyPod.podspec:
s.dependency "RxSwift", "~> 3.0.1"
However, while developing MyPod, how can I actually use the dependency?
import RxSwift
// ^
// No such module 'RxSwift'
public class MyClass { //...
Is there a step I'm missing, or some common convention? It looks like some other projects like Moya are using Carthage to build dependencies while developing. Should I be doing that, or maybe adding a Podfile?
I know that this shouldn't be a problem for an Example App located within the repo, which would have its own Podfile. However, I'd like to still have tests located at top level, outside of the Example App, and to be able to actually build the framework while working on it, again, outside of an Example App.
I can't speak to whether or not to use CocoaPods or Carthage. Both have their strong points and weak points. Plus the decision should be made considering many factors, some of which you might not be able to control (like a client that insists you use CocoaPods!) So I'll skip that part.
However, to your question, indeed a pod you are developing can depend on another pod. You already have the correct s.dependency line. That's necessary.
However, I suspect that the reason why you were not able to reference the dependent pod could be because you did not have a Podfile in your 'tester/example' project and/or you did not do a pod install after adding the dependency in your Podspec.
The reason for this is requirement I suspect is that since the Podspec is not actually processed at all by Xcode, you're not actually downloading (or compiling) the dependency.
Instead, when you do the pod install (via command line of course), CocoaPods will create a Pods project with your development pod, the pods you depend on (in Podspec) as well as any other pods in your Podfile.
To test this theory, I:
Created a new pod (using CocoaPod's own 'pod lib create' (https://guides.cocoapods.org/making/using-pod-lib-create.html).
Opened the workspace that CocoaPod created for me and edited the Podspec to add the dependency s.dependency 'RxSwift', '~> 3.0.1'.
Added another pod in my Example App's Podfile (to demonstrate the difference between Podfile dependencies and Podspec dependencies.)
Performed pod install in the Example App's folder.
Edited my Pod's class to do something useful AND to add the import RxSwift line.
Added a label to my Example App ("Hello World" of course).
Used PureLayout to do all the auto layout constraints for the label (and to demonstrate how the Example project has access to both pods - the development pod as well as the referenced pod PureLayout.)
You can check out the demo I created on my public GitHub:
https://github.com/ericwastaken/CocoaPod-Dependency-Demo
Honestly, I've created several pods using the pod lib create and it does indeed create a nice structure that has always worked for me. For this reason, I would recommend always using it to create your pod's skeleton.
Xcode 8 comment: pod lib create still seems to create a Swift 1.x project. So, right after you use this tool, when you open Xcode, you'll be offered to "convert" to a newer version of Swift. I would let that conversion happen right then and there (the first time) so that you can be in Swift 2.x or 3.x syntax (you choose).
I ended up using Carthage to build the framework dependencies. I imagine I could have used CocoaPods to do it as well. However, that would have required that I start using a workspace, and I didn't want to have to do that so as to keep changes as minimal as possible.
Also, with Carthage, it didn't require that I add a new Podfile/Podfile.lock, since Carthage will use the existing Cartfile/Cartfile.resolved that's already there. That's because Carthage uses the Cartfile.resolved when using the framework in another project and when building the framework on its own. Whereas, with CocoaPods, *.podspec is used when using the framework in another project but Podfile.lock (if you've added a Podfile) is required to install dependent pods in the framework itself.
This was a very challenging problem to solve, and required a combination of a few solutions pieced together. #EricWasTaken's solution helped, as well as adding:
source 'https://github.com/CocoaPods/Specs.git'
to the top of my Podfile. Then navigating to the Example app and run
pod repo update
pod install
Now the framework I am creating can find the cocoapods my framework requires.

Pod update has fatally altered app

My perfectly working app used to have an Xcode Project Navigator as shown below.
iOS 10 requirements meant I had to upgrade Xcode to 8.1, which meant upgrading the entire Mac OS to Sierra and also translating the whole app to Swift 2.3.
Needless to say, this caused errors, one of which was an issue with PubNub. However, apart from this new build error the app structure was the same and everything seemed ok after dealing with all the layout issues.
I was requested to run the following steps to try to solve the PubNub pod error despite me warning that previous attempts to deal with the pod file caused fatal errors that were ultimately unrecoverable.
Install all iOS simulators after Xcode update
Open Xcode preferences (Cmd+,) and navigate to ”Locations” tab where will be shown path to ”DerivedData” folder
Click on small circle with arrow on the right side of shown ”DerivedData” path to open it in Finder
Quit Xcode
Remove ”DerivedData” folder
Clean up CocoaPods (if integrated with it) caches by entering this in Terminal:
rm -rf ~/Library/Caches/CocoaPods
From project root (where Podfile is located) run this in Terminal:
pod deintegrate MyApp.xcodeproj
Remove from project root (where Podfile is located) Podfile.lock file
From project root (where Podfile is located) run this in Terminal: pod update
Launch Xcode (hit Shift + Cmd + K just in case)
Try build project
After doing all this my Project Navigator now looks like this.
As you can see, I've lost a load of stuff including the pod file etc. As suspected, my app is now fatally wounded.
My bridging header is red, Restkit.h is red and all pod references gone.
My project root in Finder has the Pods folder and pod file etc, however if I try to drag folders into the project from Finder they do not show as they used to - e.g., folders are blue color not yellow.
I'm on Xcode 8.1 and Cocoapods 1.1.1.
How can I recover my app?
EDIT: If it helps, here is the link to my unsolved question in January which was the last time I dared touch the pod file at all until now. The consequences of this situation are the same as before - the difference is that in January I was ditching 2 weeks work, now I'm looking at ditching 10 months' work.
RestKit.h never found in Xcode project
Podfile:
pod 'RestKit', '~> 0.24.0'
pod 'SimpleKeychain'
pod 'AWSS3'
pod 'VideoCore'
pod 'SDWebImage', '~>3.7'
pod 'SVPullToRefresh'
pod 'PubNub', '~> 3.7.11'
pod 'MZFormSheetController'
Result of pod update in Terminal:
Update all pods
Updating local specs repositories
Performing a deep fetch of the master specs repo to improve future performance
warning: inexact rename detection was skipped due to too many files.
CocoaPods 1.2.0.beta.1 is available.
To update use: sudo gem install cocoapods --pre
[!] This is a test version we'd love you to try.
For more information, see https://blog.cocoapods.org and the CHANGELOG for this version at https://github.com/CocoaPods/CocoaPods/releases/tag/1.2.0.beta.1
Analyzing dependencies
[!] The dependency RestKit (~> 0.24.0) is not used in any concrete target.
The dependency SimpleKeychain is not used in any concrete target.
The dependency AWSS3 is not used in any concrete target.
The dependency VideoCore is not used in any concrete target.
The dependency SDWebImage (~> 3.7) is not used in any concrete target.
The dependency SVPullToRefresh is not used in any concrete target.
The dependency PubNub (~> 3.7.11) is not used in any concrete target.
The dependency MZFormSheetController is not used in any concrete target.
From the pod update logs seems like CocoaPods can't find any target where the libraries have to be applied.
Can you try something like this in your Podfile?
target 'YOUR_TARGET_NAME' do
pod 'RestKit', '~> 0.24.0'
pod 'SimpleKeychain'
pod 'AWSS3'
pod 'VideoCore'
pod 'SDWebImage', '~>3.7'
pod 'SVPullToRefresh'
pod 'PubNub', '~> 3.7.11'
pod 'MZFormSheetController'
end
Not sure if it will fix the error you have.

Using cocoapods in a framework

I created an iOS framework that uses a library (RestKit) via CocoaPods.
In the application project that uses my framework I also use CocoaPods to include other libraries. I had to include the library from the framework as the project didn't compile otherwise.
Everything works fine, but as expected when I launch the application I get:
Class X is implemented in both /private/var/mobile/Containers/Bundle/Application/[...]/Application.app/Frameworks/Framework.framework/Framework and /private/var/mobile/Containers/Bundle/Application/[...]/Application.app/Application. One of the two will be used. Which one is undefined." in several classes from the libraries.
Is there any way in CocoaPods or in the build process to prevent having duplicate libraries when they're already being used?
Some more context to my question. Here's what I did:
Created a framework project as a Cocoa Touch Framework. Initially I added just a Podfile with a dependency for RestKit as following:
pod 'RestKit', '~>0.23'Then I removed the Podfile and just added a podspec as in the comment by #Paula Chavarría.
Created the app project. Added a Podfile with other dependencies and also the dependency to the framework as #Paula Chavarría also mentioned.
When I build the app project the framework fails building because it can't find the right headers.
I changed the header search path for the framework but it doesn't seem to be enough for the build to be successful.
Do I need to have also a Podfile in the framework? As I said in my original question, I did that at first and I ended up having duplicate libraries and that's what I'm trying to avoid in the first place.
Is there any way to tweak the Podfile or the configurations generated by it and use the headers in the app and link with the libraries in the app?
What am I missing here?... Thanks in advance! :)
If you are using Cocoapods on the application project you can create a private pod for the iOS framework. To do so you have to create a .podspec file in order to add the conflicting dependency. For Restkit the .podspec file would be like this:
Pod::Spec.new do |s|
s.name = "MyFramework"
...
s.dependency 'RestKit', '~> 0.23'
end
You can read more about these files here: http://guides.cocoapods.org/making/specs-and-specs-repo.html
After that you just have to add a dependency of your framework on the application project Podfile. You can do so through a local path or through a version control system.
pod 'MyFramework', :path => './../my-framework'
pod 'MyFramework', :git => 'https://url/to/my-framework.git', :tag => '0.0.1'

Making a private cocoapod with dependencies on other cocoapods

I've read all the tutorials (some less deeply than others), and discovered that there is a huge focus on using the pod lib create command and how to get your new cocoapod into the the podspec repo and available to other developers, but they are all missing the middle part involving actually setting up and developing your pod, Xcode example project, etc..
I'm trying to make a cocoapod for internal use that has dependencies on other pods. I told pod lib create that I wanted an example project and now I need to be able to build and run it using the pods it depends on. I'm not clear on how I actually get those pods to download. I understand that there is a podspec syntax for specifying dependencies:
spec.dependency 'SOMEPOD', '~> VER.0', but that doesn't do much for my example project.
Am I supposed to make a Podfile in the folder with my example project? Does that conflict with the podspec somehow? Do I need to include the pod I'm making in that podfile? Should I not be using an example project and just be developing my pod in conjunction with a test project that pulls my pod in like any other cocoapod?
Also, when all my testing is said and done, does the example project get distributed with the pod and set up as a weird sub-target in whatever project uses the pod? Or do I eventually have to make a different repo that just has the pod (without the example project)?

Resources