{"id":17224829,"url":"https://github.com/pseudomuto/retired","last_synced_at":"2025-04-14T00:44:46.635Z","repository":{"id":46079313,"uuid":"55260268","full_name":"pseudomuto/Retired","owner":"pseudomuto","description":"A simple framework to help recommend/force app updates and sunset old versions","archived":false,"fork":false,"pushed_at":"2020-11-30T20:03:07.000Z","size":71,"stargazers_count":4,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-13T22:03:56.328Z","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/pseudomuto.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-04-01T20:26:07.000Z","updated_at":"2019-04-23T00:53:44.000Z","dependencies_parsed_at":"2022-08-30T21:30:16.623Z","dependency_job_id":null,"html_url":"https://github.com/pseudomuto/Retired","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pseudomuto%2FRetired","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pseudomuto%2FRetired/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pseudomuto%2FRetired/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pseudomuto%2FRetired/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pseudomuto","download_url":"https://codeload.github.com/pseudomuto/Retired/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248804721,"owners_count":21164127,"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-10-15T04:12:05.060Z","updated_at":"2025-04-14T00:44:46.612Z","avatar_url":"https://github.com/pseudomuto.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Retired (iOS)\n\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![Version](https://img.shields.io/cocoapods/v/Retired.svg?style=flat)](http://cocoapods.org/pods/Retired)\n[![License](https://img.shields.io/cocoapods/l/Retired.svg?style=flat)](http://cocoapods.org/pods/Retired)\n[![Platform](https://img.shields.io/cocoapods/p/Retired.svg?style=flat)](http://cocoapods.org/pods/Retired)\n[![Tests](https://travis-ci.org/pseudomuto/Retired.svg?branch=master)](https://travis-ci.org/pseudomuto/Retired)\n\nA simple framework to help recommend/force app updates and sunset old versions\n\n## Installation\n\n### Carthage\n\nAdd the following to your Cartfile:\n\n```\ngithub \"pseudomuto/Retired\" ~\u003e 3.0\n```\n\n### Cocoapods\n\nAdd this to your Podfile:\n\n```\npod \"Retired\", \"~\u003e 3.0\"\n```\n\n### Swift Package Manager\n\nAdd the dependency in your Package.swift file:\n\n```swift\nimport PackageDescription\n\nlet package = Package(\n  ...\n  ...\n  dependencies: [\n    .Package(url: \"https://github.com/pseudomuto/Retired.git\", majorVersion: 3)\n  ],\n  ...\n  ...\n)\n```\n\n## Usage\n\n### The Versions File\n\nYou'll need to host a JSON file on a server somewhere that defines options like whether or not an update is required,\nrecommended or not necessary.\n\nThe file also defines the messaging to be displayed in each case. For example, if the user has version 1.0 installed\n(and the file below is used), when the you call `Retire.check` the supplied message in the completion block will be \nthe `forced` one.\n\nIf they're running 1.1, you'd get the recommended message, and if they're running 2.0 no update would be required.\n\nHere's an example of a versions file:\n\n```json\n{\n  \"messaging\": {\n    \"forced\": {\n      \"title\": \"App Update Required\",\n      \"message\": \"A new version of the app is available. You need to update now\",\n      \"continueButtonText\": \"Let's do this\"\n    },\n    \"recommended\": {\n      \"title\": \"App Update Available\",\n      \"message\": \"A new version is available. Want it?\",\n      \"continueButtonText\": \"I want it\",\n      \"cancelButtonText\": \"No thanks\"\n    }\n  },\n  \"versions\": [\n    { \"version\": \"1.0\", \"policy\": \"force\" },\n    { \"version\": \"1.1\", \"policy\": \"recommend\" },\n    { \"version\": \"2.0\", \"policy\": \"none\" }\n  ]\n}\n```\n\nThere are two types of objects here; message and version.\n\n**message**\n\n* `title` - The title of the alert (e.g. New Version Available)\n* `message` - The message to be displayed (e.g. There's a new version available)\n* `continueButtonText` - The label for the button that links to the app store\n* `cancelButtonText` - The (optional) label for the cancel button (intended for recommended updates only)\n\n**version**\n\n* `version` - The version of the app (pulled from `CFBundleShortVersionString`)\n* `policy` - One of `force`, `recommend` or `none`\n\n### Checking Status in Your App\n\nI don't wanna tell you how to handle displaying alerts or anything, but here's what I did in the example app (if you\nopen the workspace you'll see it in AppDelegate.swift).\n\nFirst, I made an extension on `Message`\n\n```swift\nextension Message {\n  func presentInController(controller: UIViewController?) {\n    let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)\n    alert.addAction(UIAlertAction(title: continueButtonText, style: .Default, handler: goToAppStore))\n\n    if cancelButtonText != nil {\n      alert.addAction(UIAlertAction(title: cancelButtonText, style: .Cancel, handler: nil))\n    }\n\n    controller?.presentViewController(alert, animated: true, completion: nil)\n  }\n\n  private func goToAppStore(action: UIAlertAction) {\n    UIApplication.sharedApplication().openURL(iTunesURL)\n  }\n}\n```\n\nThen, in `applicationDidFinishLaunching:withOptions`, I configured `Retired` with the URL to the versions file:\n\n```swift\nfunc application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -\u003e Bool {\n  let versionURL              = NSURL(string: \"https://example.com/versions.json\")!\n  let intervalBetweenRequests = 60 * 60 * 24 // one day between recommended app updates\n\n  Retired.configure(versionURL, suppressionInterval: intervalBetweenRequests)\n  return true\n}\n```\n\nFinally, in `applicationDidBecomeActive`, I query the status and show a message if necessary:\n\n```swift\nfunc applicationDidBecomeActive(application: UIApplication) {\n  // you should catch the error in production apps\n  try! Retired.check() { updateRequired, message, error in\n    guard updateRequired else { return }\n\n    // handle error (non 200 status or network issue)\n\n    if let message = message {\n      message.presentInController(application.keyWindow?.rootViewController)\n    }\n  }\n}\n```\n\n## LICENSE\n\nCopyright (c) 2016 pseudomuto \u003cdavid.muto@gmail.com\u003e\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpseudomuto%2Fretired","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpseudomuto%2Fretired","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpseudomuto%2Fretired/lists"}