I am using Alamofire in my app and I would like to print the version number to the logs during app start. Is there a way to access the version number programatically?
Determine version number of Alamofire programatically?
67 Views Asked by D.D. AtThere are 2 best solutions below
On
Since you are using Swift Package Manager, and as stated in previous answer of Jon Shier, the version isn't available publicly. It's there but accessible only inside the framework.
Until then (as stated Alamofire might make the version public in the future), this is a little work around steps. I haven't fully tested it, I just checked the decoding and the "string output", I didn't go up to the Build Phase part, but I'll give you the main directive that I think should make it work.
What you could do is have a little script during build phase that would read the Package.resolved and generate a file with all the version. Add that file to your Target and that should be good.
SwiftGen, etc use this behavior to generate "safe" assets (with the help of stencil, etc.)
You need to find your Package.resolved first.
Mine is at ./MyProject.xcworkspace/xcshareddata/swiftpm/Package.resolved since I use a Workspace. In case of only a PBXProjet, I'll let you find it.
You could use different languages for the script, but since we are Swift developer, I'll go with that.
Main Code:
The code could be:
struct ResolvedPackage: Decodable {
let packages: [Package]
struct Package: Decodable {
let name: String
let state: State
struct State: Decodable {
let version: String
}
enum CodingKeys: String, CodingKey {
case name = "identity"
case state
}
}
enum CodingKeys: String, CodingKey {
case packages = "pins"
}
}
do {
let path = "pathOfThePackage.resolved"
let jsonData = try Data(contentsOf: URL(fileURLWithPath: path))
let decoded = try JSONDecoder().decode(ResolvedPackage.self, from: jsonData)
var lines: [String] = []
lines.append("//AutoGenerated Code\n")
lines.append("#import Foundation\n")
lines.append("struct SPMVersion {")
decoded.packages.forEach {
lines.append("\t static let \($0.name) = \"\($0.state.version)\"")
}
lines.append("}")
let output = lines.joined(separator: "\n")
print(output)
try output.write(toFile: "PathOfTheNewSwiftFileYouWant.swift", atomically: true, encoding: .utf8)
} catch {
print("Error while retrieving Package.resolved content: \(error)")
}
Sample output:
//AutoGenerated Code
#import Foundation
struct SPMVersion {
static let alamofire = "5.6.4"
static let alamofireimage = "4.2.0"
}
In use:
- Make that code a "Swift Script" (I'll let you dig into that: more or less add
#!/usr/bin/swift&#import Foundation, at the start of a new .swift file, and make it executable withchmod). - Execute the script in the build phases by adding a
New Script Phaseand call it there from "Bash code". - Add PathOfTheNewSwiftFileYouWant.swift to your target.
Going further:
Of course, this code is currently "quick and dirty", you might dig into it with parametering a few things:
- Path of the PackageResolved in Script Parameter
- Path of the Output Swift file in Script Parameter
- Use a more "cleaner Swift Code" output, using Stencil or I think SwiftSyntax.
- Grab other parameters from the Package.resolved if needed, or modify the decoding (I did it quick and didn't want to use custom
init(from decoder:)). - Parse also the CocoaPods/Carthage resolved files if needed to have all of your libs versions (but check before hand if they don't generate already a "user friendly" resume of the versions).
Note that Package.resolved doesn't seem to list the dependencies (on my last test), so you shouldn't be able to get theses versions.
Alamofire's version is part of its default
User-Agentheader, so if you're logging your network request, the version should be part of that already. I can see that it could be useful for it to be public so it can be part of custom logging or other headers, so I'll look into making it public.