Library checks for updates using configuration from some resource.
- Load update configuration from network resource
- Use predefined parser for parsing update configuration in JSON format
- Make asynchronous loading and use callback for notifying result
- iOS 11.0+
- macOS 10.13+
- Xcode 14.0+
The easiest way to use Prince of versions in your project is using the CocaPods package manager.
See installation instructions for CocoaPods if not already installed
To integrate the library into your Xcode project specify the pod dependency to your Podfile
:
platform :ios, '11.0'
use_frameworks!
pod 'PrinceOfVersions'
or
platform :osx, '10.13'
use_frameworks!
pod 'PrinceOfVersions'
run pod install
pod install
For the Carthage installation and usage instruction, you can check official quick start documentation.
To integrate the library into your Xcode project, specify it in your Cartfile
:
github "infinum/ios-prince-of-versions"
Run carthage update
.
To install Prince of Versions from the Swift Package Manager, you should:
- In Xcode 11+ select File → Packages → Add Package Dependency
- Enter project's URL: https://github.com/infinum/ios-prince-of-versions.git
For more information, check Swift Package Manager .
For JSON file details and formatting, read JSON specification.
let princeOfVersionsURL = URL(string: "https://pastebin.com/raw/0MfYmWGu")!
PrinceOfVersions.checkForUpdates(
from: princeOfVersionsURL,
completion: { [unowned self] response in
switch response.result {
case .success(let updateResultData):
print("Update version: \(updateResultData.updateVersion)")
print("Installed version: \(updateResultData.updateInfo.installedVersion)")
print("Update status: \(updateResultData.updateStatus)")
case .failure:
// Handle error
break
}
}
)
When checking for updates, be it for AppStore or other sources, you can provide a cachePolicy parameter. The cachePolicy parameter determines which request cache policy will be used for network requests.
The initial value for the default URLSession
configuration uses .useProtocolCachePolicy, which shouldn't be the default behavior for Prince of Versions; we want to refresh the data from the server every time. That's why we defaulted the value to .reloadIgnoringLocalCacheData. If you want to change the default behavior, you can always provide a different cache policy that suits your needs.
For each requirement key listed in a configuration, there should exist a requirement check closure. If you don't provide it, the requirement will be considered as not met, and the whole configuration will be discarded. However, if you provide requirement check, but JSON doesn't contain requirement key for your check, the check will be ignored.
If the JSON contains
required_os_version
key under requirements, the library itself will handle checking if that requirement is met. You don't need to provide a closure.
Here is the example of how to add requirement check closures.
let options = PoVRequestOptions()
options.addRequirement(key: "region") { (value) -> Bool in
guard let value = value as? String else { return false }
// Check OS localisation
return value == "hr"
}
options.addRequirement(key: "bluetooth") { (value) -> Bool in
guard let value = value as? String else { return false }
// Check device bluetooth version
return value.starts(with: "5")
}
let princeOfVersionsURL = URL(string: "https://pastebin.com/raw/0MfYmWGu")!
PrinceOfVersions.checkForUpdates(from: princeOfVersionsURL, options: options, completion: { [unowned self] response in
switch response.result {
case .success(let updateResultData):
print("Update version: \(updateResultData.updateVersion)")
print("Installed version: \(updateResultData.updateInfo.installedVersion)")
print("Update status: \(updateResultData.updateStatus)")
case .failure:
// Handle error
break
}
})
If you consider following JSON example and requirement checks added in the example above, the first configuration will be considered as not appropriate since requirement check for free-memory
is not defined. However, all requirements in the second configuration are met and its values will be returned.
...
{
"required_version":"1.2.3",
"last_version_available":"1.9.0",
"notify_last_version_frequency":"ALWAYS",
"requirements":{
"required_os_version":"8.0.0",
"region":"hr",
"bluetooth":"5.0",
"free-memory":"80MB"
},
},
{
"required_version":"1.2.3",
"last_version_available":"2.4.5",
"notify_last_version_frequency":"ALWAYS",
"requirements":{
"required_os_version":"12.1.2",
"region":"hr",
"bluetooth":"5.0"
},
}
...
If you don't want to manage the JSON configuration file required by checkForUpdates
, you can use checkForUpdateFromAppStore
. This method will automatically get your app BundleID and it will return version info fetched from the App Store.
However, updateStatus
result can only assume values UpdateStatus.noUpdateAvailable
and UpdateStatus.newUpdateAvailable
. It is not possible to check if update is mandatory by using this method and data provided by the AppStore.
PrinceOfVersions.checkForUpdateFromAppStore(
trackPhaseRelease: false,
notificationFrequency: .once,
completion: { result in
switch result {
case .success(let appStoreResult):
print("Update version: \(appStoreResult.updateVersion)")
print("Installed version: \(appStoreResult.updateInfo.installedVersion)")
print("Update status: \(appStoreResult.updateStatus)")
case .failure:
// Handle error
}
})
It is possible to define update notification frequency with the parameter notificationFrequency
. If you set the parameter value to NotificationType.once
, only the first time this methods is called, it will return UpdateStatus.newUpdateAvailable
if a new version exists, every subsequent call it will return UpdateStatus.noUpdateAvailable
for that specific version. If described behaviour doesn't suit your needs, you can always set this parameter to NotificationType.always
and have updateStatus as UpdateStatus.newUpdateAvailable
when a new version is available.
If your application has multiple targets you might need more than one JSON configuration file. If that is the case, do not forget to set a different URL for each target.
If you use certificate pinning for secure communication with the server holding your JSON version file, put the certificate in the app Resource folder (make sure that the certificate has one these extensions: ".cer"
, ".CER"
, ".crt"
, ".CRT"
, ".der"
, ".DER"
).
Prince Of Versions will look for all the certificates in the main bundle. Then set the shouldPinCertificates
parameter to true
in the loadConfiguration
method call.
let url = URL(string: "https://pastebin.com/raw/0MfYmWGu")
PrinceOfVersions.checkForUpdates(from: url, shouldPinCertificates: true) { (response) in
switch response.result {
case .success(let result):
if let latestVersion = result.updateInfo.latestVersion {
print("Is minimum version satisfied: ", latestVersion)
}
case .failure(let error):
print(error.localizedDescription)
}
}
PrinceOfVersions does not collect any user data. We have provided a privacy manifest file that can be included in your app.
Feedback and code contributions are very much welcome. Just make a pull request with a short description of your changes. By making contributions to this project you give permission for your code to be used under the same license.
Maintained and sponsored by Infinum.