AppGuard is a guard πββοΈ for your iOS app, to check / force users to update your app or show what changed.
- iOS 9.0+
- Swift 4.2+
- Xcode 10.0+
To run the example project, clone the repo, and run pod install
from the Example directory first.
StarsKit is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'AppGuard'
Today we have third parties dependencies, but the purpose is to avoid them the most.
We also wan to have a quick available library and significant customization, we use one dependency:
- Jelly: a simple UI component to simplify the rating transition display
AppGuard offers three default behaviors for your app to:
- Check and show to the user if a new version of your app have to be downloaded (mandatory update).
- Check and show to the user if a new version of your app should be downloaded (recommandated update).
- Show to the user what's new in the last version (update informations).
By a mecanism of revival displays, blocked or dimissable pop-up, the user will / may have to update your app according to the informations and actions displayed.
- Static configuration strings
- Cocoapods integration
- Default & configurable step transitions
- Default display algorithm behavior
- Customizable fonts, text & tint colors
- Screen actions callbacks
- Configurable with dictionary/data or remote URL: everything you want!
- Overridable layouts
- Lifecycle display events ([will/did]appear/disappear)
- Configurable key for parsing
- Firebase extension to bind Remote Config to StarsKit data
- Additional condition checking on the default check
- Carthage integration
- Use localizable or configuration strings
- Default localizable strings :
-
- EN
-
- FR
- Overridable localizable strings
- Customizable display algorithm behavior
You can specify metrics to trigger the default display behavior or use your own one.
- Disable/enable the component
- Version code (bundleVersion)
- Static configuration strings
- Maximum of days between display
- Mandatory type: screen properties
- Recommanded type: Feedback screen properties
- Changelog type: Store review screen properties
// Simply use the prepare method for default configuration properties
AppGuard.default.prepare()
// Configure the dataSource
AppGuard.default.dataSource = self
// And optionnaly the uiDelegate
AppGuard.default.uiDelegate = self
It's necessary to implement it to indicate the presenter controller to AppGuard
and optionnally do something with the UIImageView
.
// MARK: - AppGuardDataSource
extension ViewController: AppGuardDataSource {
func configureImageView(_ imageView: UIImageView?) {
// Do anything with the UIImageView,
// 1- Download an Image with Kingfisher
// 2- Add a Lottie animated subview on it
}
func guardPresenterController() -> UIViewController? {
return self
}
}
The UI delegate will send you lifecycle and user interaction events.
It's strongly recommanded to implement didChooseLater:
and didChooseAction:
.
// MARK: - AppGuardUIDelegate
extension ViewController: AppGuardUIDelegate {
func guardControllerWillAppear(for context: AppGuardContextType) {
print("guardControllerWillAppear")
}
func guardControllerDidAppear(for context: AppGuardContextType) {
print("guardControllerDidAppear")
}
func guardControllerWillDisappear(for context: AppGuardContextType) {
print("guardControllerWillDisappear")
}
func guardControllerDidDisappear(for context: AppGuardContextType) {
print("guardControllerDidDisappear")
}
func didChooseLater(for context: AppGuardContextType) {
print("didChooseLater")
}
func didChooseAction(for context: AppGuardContextType) {
if context == .mandatoryUpdate || context == .recommandedUpdate {
UIApplication.shared.openURL(URL(string: "https://itunes.apple.com/fr/app/<your app ID>")!)
}
}
}
AppGuard use a simple Dictionnary data to update its configuration.
let configurationData // a [String: Any?] instance from JSON file or static dictionnary or anything else
AppGuard.default.updateConfig(from: configurationData)
// Ask the guard πββοΈ if we can pass
AppGuard.default.displayUpdateStatus()
// You can force it too πββοΈπ€·ββοΈ
AppGuard.default.displayUpdateStatus(forced: true)
βΉοΈ You can optionnaly specify the keys binding with the AppGuardConfigurationKeysBinder
, to bind your source configuration to the AppGuard configuration. By default, the AppGuardConfigurationKeys
rawValues will be used.
Imagine that you have a custom JSON structure like that:
{
"my_deeplink_key": "http://www.google.custom",
"my_dialog_type_key": 1,
"my_content_key": "Custom content text",
"my_action_label_key": "Custom action label",
"my_changelog_content_key": "Custom changelog text",
"my_title_key": "Custom title",
"my_imageurl_key": "Custom image URL",
"my_laterButtonLabel_key": "Later",
"my_maxDaysBetweenDisplay_key": 3,
"my_versionCode_key": 2
}
Change the default keys binding with the AppGuardConfigurationKeysBinder
:
let binding: [String: String?] = [AppGuardConfigurationKeys.deeplink.rawValue: "my_deeplink_key",
AppGuardConfigurationKeys.dialogType.rawValue: "my_dialog_type_key",
AppGuardConfigurationKeys.content.rawValue: "my_content_key",
AppGuardConfigurationKeys.actionButtonLabel.rawValue: "my_action_label_key",
AppGuardConfigurationKeys.changelogContent.rawValue: "my_changelog_content_key",
AppGuardConfigurationKeys.title.rawValue: "my_title_key",
AppGuardConfigurationKeys.imageUrl.rawValue: "my_imageurl_key",
AppGuardConfigurationKeys.versionCode.rawValue: "my_versionCode_key"]
AppGuardConfigurationKeysBinder.bindConfigurationKeys(binding)
You can simply override the .xib
name of default controllers:
AppGuardChangelogViewController
AppGuardUpdateViewController
For instance, create a AppGuardChangelogViewController.xib
with the custom file's owner set to the StarsKit module. IBOutlets are optionnals so you decide what to override or not.
Don't forget the IBAction links!
NB: UIViewController
custom classes support will be available soon.
The AppGuardGraphicContext
can be set with your own values.
AppGuard.default.graphicContext.actionButtonBackgroundColor = UIColor.ex.fromHexa("#17b8c5")
AppGuard.default.graphicContext.jellyCustomTransition = myCustomJellyPresentation
AppGuard.default.graphicContext.buttonCornerRadius = 5
Customizable properties are:
cornerRadius: CGFloat
roundedButton: Bool
actionButtonBackgroundColor: UIColor?
actionButtonTitleColor: UIColor
actionButtonFont: UIFont
laterButtonBackgroundColor: UIColor?
laterButtonTitleColor: UIColor
laterButtonFont: UIFont
titleFont: UIFont
titleColor: UIColor
contentFont: UIFont
contentColor: UIColor
image: UIImage?
jellyCustomTransition: JellyPresentation
AppGuard uses Jelly fro customizable transitions. You can specify your own via the jellyCustomTransition
property in the AppGuardGraphicContext
.
Go to Jelly repo for more information.
You can use the configurations strings or the Localizable ones, which you can override to in your app bundle.
If your app already use Firebase, why not use the Firebase Remote Config feature? AppGuard will be able to convert your associated Firebase remote configuration object to a readable data dictionnary for itself π.
Add the Firebase Podspec
pod 'AppGuard/FirebaseRemoteConfig'
// Bind the properties keys if needed before
// or use the default ones in the remote config
let remoteConfig = RemoteConfig.remoteConfig()
remoteConfig.fetch(withExpirationDuration: 1.second) { (status, _) in
remoteConfig.activateFetched()
AppGuard.default.updateConfig(from: remoteConfig)
AppGuard.default.checkUpdateStatus()
}
Made in π«π· by the Smart&Soft iOS Team.
AppGuard is available under the MIT license. See the LICENSE file for more info.