Migrating from carthage to swift package manager - ios

I have a project that has multiple external dependencies as well as in house ones such as analytics, api, interfaces, that are all integrated with Carthage. I wanted to gradually migrate all of them to SPM starting with the analytics module.
I've restructured my analytics module to a package and integrated it to main my project using SPM (all worked well!). I did the same for all the other modules that also depend on analytics and removed the references from cartfile, .resolved and .private files.
The issue that I'm facing now is that I'm not sure how to remove the integration done by carthage. Even removing the reference from all cartfiles and from framework and libraries, when I run carthage bootstrap it looks like it still fetches that module and adds the framework to my Carthage folder, which I don't want to.
It's the first time I'm using Carthage, so I'm not sure if I might be missing some step when removing just one dependency. If anyone with more experience could help I'd really really appreciate it =]

Related

How not to carthage update every time I update my own Carthage framework

I have an iOS project that uses a Carthage framework which I created for myself. For convenience let's name them as following.
MAIN_ PROJECT
MY_FRAMEWORK
I make changes to MY_FRAMEWORK often that each time I change it I need to run carthage update on MAIN_PROJECT which take quite a time.
I wonder if there is a way to make changes to MY_FRAMEWORK and affect changes to MAIN_PROJECT without calling carthage update but still keeping MY_FRAMEWORK a separated repository framework so I can be used from other projects.
If it is an option to integrate it into your project using Swift Package Manager then Apple has a solution for you:
Swift packages are a convenient and lightweight solution for creating a modular app architecture and reusing code across your apps or with other developers. Over time, you may want to develop your published Swift package in tandem with your app, or create a sample app to showcase its features. To develop a Swift package in tandem with an app, you can leverage the behavior whereby a local package overrides a package dependency with the same name:
Add the Swift package to your app as a package dependency instead of a local package, as described in Editing a Package Dependency as a Local Package.
Develop your app and your Swift package in tandem, and push changes to their repositories.
If you release a new version of your Swift package or want to stop using the local package, remove it from the project to use the package dependency again.
Also have a look at detailled instructions with links to related topics.

Package.swift together with Xcode 11 Project, how to use Carthage and SPM alongside?

I feel caught between the Carthage world and the Swift Package Manager (SPM) world, like being stuck in purgatory.
I'm developing a Swift library/SDK, and up until now, I've been using Carthage for dependencies. But since SPM finally works with iOS, I feel it would be great for people who want to use this library to be able to include it via SPM.
However, I've hit a wall. One of my dependencies, namely BitcoinKit works with Carthage but SPM support is broken.
In order to distribute my library, I need to have a Package.swift file, and some other critteria (README, source files in Sources, and tests in Tests). I also need to declare my dependencies in said Package.swift file, so that SPM recursivley can resolve all dependencies (when people install my library via SPM). Here's where I get stuck...
Since I'm still using Carthage I need a Xcode Project file to set up this Carthage dependency. But now my source files cannot import the SPM dependencies. They aren't found. Seems like I MUST include the SPM package dependencies using Xcode and Add Package Dependency feature (Apple doc here). This is not what I want right, I want my Package.swift file to declare the same versions of the SPM packages my library uses. To make it clear, this problem arises due to the fact that I need a Xcode project, due to Carthage.
So I thought maybe I could build BitcoinKit with Carthage (as I'm doing now), and include the built binary (.Carthage/Build/iOS/BitcoinKit.framework) my library, referencing it in Package.swift, but that does not work since SPM does not (yet?) support binaries (relevant Swift Forum Thread).
So what are my options?
1) Wait until someone smart fixes the broken SPM support in BitcoinKit (I've tried myself and failed), and then remove my Xcode project file and complete the transition of to only SPM and for now stick with Carthage...
2) Try to use SPM packages internally in my library installed through Xcode Add Package Dependency feature and manually sync those versions with the ones I declare in my Package.swift. Will that even work? Ugh, terrible solution anyway.
3) Hope to include BitcoinKit.framework built through Carthage as a binary when SPM supports it? When? Might take a while?
4) BitcoinKit also works with Cocoapods, but I guess that gets me nowhere, even worse actually, since Cocoapods creates a .xcworkspace file.
5) Wait until Apple hopefully (does anyone know if there are any plans?) changes so that we include Swift Packages via Package.swift file even when used together with an Xcode project file? That we I could keep on using Bitcoinkit via Carthage and only declare my SPM packages in one place and I guess SPM/Xcode/Swift would be responsible for integrating the dependencies into my Xcode project, but updated and managed through the Package.swift file...?
6) Any other alternative, real solution?
Without looking into the whole 'making bitcoinkit work with SPM' bit I think the 'linking a carthage prebuilt binary' idea sounds best as an interim solution at the very least.
It's not possible to link a binary in the package manifest (yet) but you can link it when you're building:
When building an SPM package from the command line using swift build you can link the binary using -Xswiftc or -Xlinker to pass the args -F path/to/bitcoinkit if you're linking a framework. Keep in mind each argument must have a cross argument flag before it.
When building in Xcode you should be able to solve it with an .xcconfig with the contents:
FRAMEWORK_SEARCH_PATHS = path/to/bitcoinkit
You may have to tweak it a bit but I imagine this should work, worst case having a separate .xcodeproj generated by swift package generate-xcodeproj --xcconfig-overrides myconfig.xcconfig.
There is a WalletExample in yenom/BitcoinKit on GitHub. It comes with a workspace and project.
I was able to include yenom/BitcoinKit with SPM in my Package.swift and I don't use any projects/workspaces.

iOS - update a framework

I built an app that uses a third party SDK. Recently I had to update the SDK with a new version. I removed the framework files from my application folder, copied the new ones, added them to the project, but it seems XCode is caching the old version.
I tried Clean, tried to delete Derived Data, nothing works. At this point it seems the only available option is to recreate the project and import all the source files. Obviously I am not keen on that. There must be an easy, fast solution to this issue.
Any clue?
Cocoa pods are easy to use and install.
CocoaPods is the dependency manager for Objective-C projects. It has
thousands of libraries and can help you scale your projects elegantly.
Ultimately, its goal is to improve discoverability of, and engagement
in, third party open-source libraries, by creating a more centralized
ecosystem.
However the frameworks need to be compatible with cocoa pods which most libraries are. You use terminal to install. This site may give you an idea how to install it.
Fixed it. I deleted all copies of the old SDK, whether or not they were in my project folder. Seems like XCode was linking to one of them... Another mystery.

Cocoa Touch Framework Swift with embed libraries

I am working on a suite of applications that contain common modules.
 
I want to store the common modules in a Cocoa Touch Framework.
This framework may also contain the libraries and Alamofire and SwiftyJSON because they are widely used in the modules.
 
Currently, despite the many tutorials, articles, etc. read on the internet, I cannot get a stable solution.
Is it possible to integrate the frameworks Alamofire and SwiftyJSON within the framework custom or is it better to integrate them in the different projects consuming the framework (they will also need individually) ?
 
Is it possible to generate a framework running on the simulator and on the phone (whatever methods: subproject or not, dynamic or static library, fat library) ?
You can absolutely do this. You currently have three options for setting this up for development and two options for deployment.
Development
Git Submodules
Git submodules are a great way to bring additional libraries into your project's repository to embed in your project. All you need to do is add the submodule, then drag the Xcode project of that library into your Xcode project so it's nested inside your project. Then you need to add the framework as a link target to your library.
Carthage
Carthage also supports git submodules through the --use-submodules flag. All you need to do is install carthage through homebrew, then create a Cartfile that adds Alamofire and SwiftyJSON using the following command.
carthage update --use-submodules
CocoaPods
CocoaPods is a dependency management system that allows you to easily pull in and deploy different versions of a given library. Since both Alamofire and SwiftyJSON support CocoaPods, you could create a Podfile, and run pod install to pull the pods into your library. I would not recommend this though as this is a pretty heavy weight approach. Instead, I would recommend using either Git Submodules or Carthage for development.
Deployment
Deployment is a MUCH different situation. Currently, there are two fairly robust deployment mechanisms for iOS and OSX that are in wide use in the OSS community (including Alamofire and Carthage).
Carthage
If you imported your git submodules using Carthage, then you may already be completely supporting Carthage deployments. It depends on whether you used a Cartfile.private file to pull in your dependencies. Given what you're trying to do, I doubt that you would use a private Cartfile and would instead use the public one. This means that you should be good to go right out of the box. Awesome!
CocoaPods
CocoaPods is much different than Carthage and has some big advantages over Carthage, at a cost. You need to create a podspec file and push that into a public or private spec repo. Then anyone can pull your pod into their project using a Podfile.
Summary
As you can see, there are MANY options here. I would highly recommend using Carthage to pull in your git submodules, then supporting both Carthage and CocoaPods for deployment. I know that's a lot of effort though, so you may want to focus on one or the other. Sorry for the massive amount of links and information, but you question leads me to believe that you would greatly benefit from all these various sources.
Hopefully that helps get you on your way to becoming a dependency development and deployment ninja.

iOS dependency management and packaging

I'm completely new to iOS development and coming from an Android background. I was starting to look at what alternatives are out there for dependency management in iOS and found out that CocoaPods seems to be the most prevalent option.
After reading a lot of links about this topic I'm kinda at a loss and wondering what is the usual way dependencies are handled in iOS.
I have two questions:
1) What would the equivalent of using gradle to generate library (.aar) projects be in iOS? If there's any equivalent option. From what I've seen one can wrap static libraries and headers into frameworks and these can be used in other apps, is this the standard way to do it?
2) If (1) is correct, does CocoaPods offer a mechanism to add frameworks as dependencies?
I don't have a Android background but from what I understand of .aar files CocoaPods does something very similar. CocoaPods uses .podspec files (described here) to generate static libraries (and soon dynamic frameworks which are new in iOS 8) that are then linked into your project.
A podspec can define source files, assets, libraries, or frameworks that a source vendors for linking into your application. So yes it does support adding frameworks as dependencies, although until iOS 8 frameworks were not supported at all on iOS.
As far as the 'standard' way to do it, I think that's based on opinion. There are a few general ways to include dependencies you can choose from.
Drag files, frameworks, and whatever else you need into your project manually. Updating these is more difficult and that also means you have to configure your .xcodeproj depending on what features that library needs (such as ARC)
Drag a provided .xcodeproj into your project, and link the relevant target from the given project. This can be nice if the library provides a project that can build a framework or static library, in this case you'd pull in that library but their project would handle custom compiler flags.
Do either of the above while including them as git submodules. Assuming nothing massive changes in the project this helps a lot with updating your dependencies.
Use CocoaPods. CocoaPods will handle all the custom linking and updates based on semantic versioning (usually).
Use Carthage. Carthage is an in- between CocoaPods and the .xcodeproj solution. It will download code based on semantic versions defined by git tags, then you drag the generated frameworks into your project.
All of these options have pros and cons and the decision normally comes down to how you feel about the control you have over the inclusion of the library, and how automated you want it to be.
I do not have android nor iOS background however I've been developing a CI tool for both platforms and here are the answers
As You mentioned this a framework and pods (libraries) from cocoapods are distributed that way. For instance, have a look at Apphance. When spec is clicked it's visible that this library will be accessible as a Apphance-Production.framework.
You add pods to Podfile and download them with pod install command. This command will made classes from Apphance accessible from the code. Some people do commit downloaded pods, other not (it's like adding jars or aars to source control).

Resources