{"id":21065092,"url":"https://github.com/prolificinteractive/bellerophon","last_synced_at":"2025-05-16T02:33:01.270Z","repository":{"id":56903612,"uuid":"49268025","full_name":"prolificinteractive/Bellerophon","owner":"prolificinteractive","description":null,"archived":false,"fork":false,"pushed_at":"2018-09-20T14:57:14.000Z","size":233,"stargazers_count":12,"open_issues_count":4,"forks_count":7,"subscribers_count":24,"default_branch":"master","last_synced_at":"2025-04-23T08:51:38.147Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/prolificinteractive.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-01-08T11:16:45.000Z","updated_at":"2023-02-26T17:05:39.000Z","dependencies_parsed_at":"2022-08-21T02:50:17.329Z","dependency_job_id":null,"html_url":"https://github.com/prolificinteractive/Bellerophon","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prolificinteractive%2FBellerophon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prolificinteractive%2FBellerophon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prolificinteractive%2FBellerophon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prolificinteractive%2FBellerophon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/prolificinteractive","download_url":"https://codeload.github.com/prolificinteractive/Bellerophon/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254456238,"owners_count":22074134,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-19T17:53:34.392Z","updated_at":"2025-05-16T02:33:00.736Z","avatar_url":"https://github.com/prolificinteractive.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BELLEROPHON #\n\n[![Travis build status](https://img.shields.io/travis/prolificinteractive/Bellerophon.svg?style=flat-square)](https://travis-ci.org/prolificinteractive/Bellerophon)\n[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Bellerophon.svg?style=flat-square)](https://img.shields.io/cocoapods/v/Bellerophon.svg)\n[![Platform](https://img.shields.io/cocoapods/p/Bellerophon.svg?style=flat-square)](http://cocoadocs.org/docsets/Bellerophon)\n[![Docs](https://img.shields.io/cocoapods/metrics/doc-percent/Bellerophon.svg?style=flat-square)](http://cocoadocs.org/docsets/Bellerophon)\n\n![Bellerophon fighting Chimera](Images/bellerophon.jpg)\n\nBellerophon is a hero of Greek mythology. He was *\"the greatest hero and slayer of monsters, alongside Cadmus and Perseus, before the days of Heracles\"*, and his greatest feat was killing the **Chimera**, a monster that Homer depicted with a lion's head, a goat's body, and a serpent's tail.\n\nSometimes in a development phase, it happens for different reasons that the app available in the store has to be killed. It could be because it contains a major issue (crash, security breach...) or for a business decision (killing the app before a Sale starts, so users are not buying before the others for example).\n\n## Description ##\n\nBellerophon is a Swift implementation of a protocol and convenient methods that allow you to either kill your app or force the users to update using the App Store. By implementing Bellerophon, you will be able to easily add the logic to present a kill state view in your app, or force update view in your app.\n\n## Requirements\n\n* iOS 9.0+\n* Xcode 8.0+\n\n## Installation ##\n\nTo use in your projects, simply add the following line to your Podfile:\n\n```bash\npod 'Bellerophon'\n```\n\nYou can then use `Bellerophon` by importing it into your files:\n\n```swift\nimport Bellerophon\n```\n\n### Configuration ###\n\nIn order to use Bellerophon, you'll have to follow these steps:\n\n1 - In your AppDelegate implementation file, import the project and register to the `BellerophonManagerDelegate`.\n\n```swift\nclass AppDelegate: UIResponder, UIApplicationDelegate, BellerophonManagerDelegate {\n\t...\n}\n```\n\n2 - Implement and configure BellerophonManager via BellerophonConfig. The configuration supports optional kill switch view, optional force update view, and many optional delegate methods. If a developer chooses to not supply a kill switch view nor a force update view\n\n```swift\nlet killSwitchView = \u003cYOUR VIEW\u003e\nlet forceUpdateView = \u003cYOUR VIEW\u003e\nlet config = BellerophonConfig(window: window, killSwitchView: killSwitchView, forceUpdateView: forceUpdateView, delegate: self)\n```\n\n3 - Start the check the app status\n\n```swift\nkillSwitchManager.checkAppStatus()\n```\n\nHere is for the Bellerophon basic implementation. Now you will need to create your own model that conforms to the Bellerophon status protocol, `BellerophonObservable`.\n\n4 - Creates your model and make it conforms to `BellerophonObservable`.\n\n```swift\nclass BellerophonModel: BellerophonObservable { }\n```\n\n5 - Implements the `BellerophonObservable` methods.\n\n```swift\n@objc func apiInactive() -\u003e Bool {\n\t...\n}\n\n@objc func forceUpdate() -\u003e Bool {\n\t...\n}\n\n@objc func retryInterval() -\u003e NSTimeInterval {\n\t...\n}\n\n@objc func userMessage() -\u003e String {\n\t...\n}\n\n@objc func setUserMessage(_ message: String) {\n\t...\n}\n```\n\n6 - Now that you have your model, you are ready to implement the `BellerophonManagerDelegate` methods in your App Delegate.\n\n```swift\nfunc bellerophonStatus(_ manager: BellerophonManager,\n                                  completion: @escaping (BellerophonObservable?, NSError?) -\u003e ()) {\n    // MAKE API CALL\n    Alamofire.request(killSwitchURL,\n                      method: .get,\n                      parameters: nil,\n                      encoding: JSONEncoding(),\n                      headers: nil)\n        .responseJSON { (response) in\n            if let json = response.result.value as? JSON {\n                let model = BellerophonModel(json: json)\n                completion(model, nil)\n            } else if let error = response.result.error as NSError? {\n                completion(nil, error)\n            }\n    }\n}\n\nfunc shouldForceUpdate() {\n\t// A force update event should occur. An alert should be displayed to redirect to the App Store.\n}\n```\n\nYour app is not ready to work with Bellerophon. If the status tells Bellerophon to kill the app, it will display a full screen view on top of everything and will keep it like that until the status API indicates that the app should work again. A timer is also starting based on the retry interval provided by the status object. Similar behavior will occur for force update view.\n\nYour API and model should be able to indicate at least these informations :\n\n* Is the API active or inactive?\n* Should the app be forced to update?\n* What is the retry interval?\n* What is the user message to display on the kill view?\n\nThe specifications that we are using at Prolific Interactive are this one:\n\n```\n{\n    \"apiInactive\": false,\n    \"forceUpdate\": false,\n    \"retryInterval\": 15,\n    \"userMessage\": null\n}\n```\n\n* `apiInactive`\n    * Determines if the API is active or not. If it is `true` the App UI should be blocked until this is `false`.\n    * Required, type: boolean\n* `forceUpdate`\n    * Determines if the App should force the user to update to the latest version. This should be used very sparingly.\n    Only in emergencies or non supported app versions.\n    * Required, type: boolean\n* `retryInterval`\n    * The time in seconds to wait to ping this endpoint until `apiInactive` is set to `false`.\n    * Required, type: integer\n* `userMessage`\n    * A message to describe the issue that is going on.\n    * Optional, type: string\n\n\n### How to test? ###\n\nCurrently there is not an easy way to test Bellerophon. The best way is either to force the response model from the API to return an API inactive state so you can see the kill switch, or use a web debugging proxy like [Charles](http://www.charlesproxy.com) to set a breakpoint on the endpoint and change the API response to deactivate the API.\n\n## Contributing ##\n\nTo report a bug or enhancement request, feel free to file an issue under the respective heading.\n\nAdditionally, JSON responses for the test project are created via [myJSON](http://myjson.com/). You are welcome to create your own urls that contain any JSON for testing purposes.\n\nIf you wish to contribute to the project, fork this repo and submit a pull request.\nproject.\n\n## License ##\n\nBellerophon is Copyright (c) 2015 Prolific Interactive. It may be redistributed under the terms specified in the [LICENSE](LICENSE) file.\n\n## Maintainers ##\n\n![prolific](https://s3.amazonaws.com/prolificsitestaging/logos/Prolific_Logo_Full_Color.png)\n\nBellerophon is maintained and funded by Prolific Interactive. The names and logos are trademarks of Prolific Interactive.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprolificinteractive%2Fbellerophon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprolificinteractive%2Fbellerophon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprolificinteractive%2Fbellerophon/lists"}