Swiftpack.co - Package - ArtSabintsev/Siren

Siren 🚨

Notify users when a new version of your app is available and prompt them to upgrade.

Travis CI Status Documentation Swift Support

CocoaPods Carthage Compatible Accio supported SwiftPM Compatible


Table of Contents


Meta

About

Siren checks a user's currently installed version of your iOS app against the version that is currently available in the App Store.

If a new version is available, a language localized alert can be presented to the user informing them of the newer version, and giving them the option to update the application. Alternatively, Siren can notify your app through alternative means, such as a custom user interface.

Siren is built to work with the Semantic Versioning system.

  • Canonical Semantic Versioning uses a three number versioning system (e.g., 1.0.0)
  • Siren also supports two-number versioning (e.g., 1.0) and four-number versioning (e.g., 1.0.0.0)

Features

Current Features

Future Features

A list of future development work can be found on Siren's Kanban Board.


Screenshots

  • The left picture forces the user to update the app.
  • The center picture gives the user the option to update the app.
  • The right picture gives the user the option to skip the current update.
  • These options are controlled by the Rules.AlertType enum.

Ports

  • Objective-C (iOS)
    • Harpy
    • Siren was ported from Harpy, as Siren and Harpy are maintained by the same developer.
    • As of December 2018, Harpy has been deprecated in favor of Siren.
  • Java (Android)
  • React Native (iOS)

Installation and Integration

Installation Instructions

| Swift Version | Branch Name | Will Continue to Receive Updates? | ------------- | ------------- | ------------- | 5.1 | master | Yes | 5.0 | swift5.0 | No | 4.2 | swift4.2 | No | 4.1 | swift4.1 | No | 3.2 | swift3.2 | No | 3.1 | swift3.1 | No | 2.3 | swift2.3 | No

CocoaPods

pod 'Siren' # Swift 5.1
pod 'Siren', :git => 'https://github.com/ArtSabintsev/Siren.git', :branch => 'swift5.0' # Swift 5.0
pod 'Siren', :git => 'https://github.com/ArtSabintsev/Siren.git', :branch => 'swift4.2' # Swift 4.2
pod 'Siren', :git => 'https://github.com/ArtSabintsev/Siren.git', :branch => 'swift4.1' # Swift 4.1
pod 'Siren', :git => 'https://github.com/ArtSabintsev/Siren.git', :branch => 'swift3.2' # Swift 3.2
pod 'Siren', :git => 'https://github.com/ArtSabintsev/Siren.git', :branch => 'swift3.1' # Swift 3.1
pod 'Siren', :git => 'https://github.com/ArtSabintsev/Siren.git', :branch => 'swift2.3' # Swift 2.3

Carthage

github "ArtSabintsev/Siren" // Swift 5.0
github "ArtSabintsev/Siren" "swift5.0" // Swift 5.0
github "ArtSabintsev/Siren" "swift4.2" // Swift 4.2
github "ArtSabintsev/Siren" "swift4.1" // Swift 4.1
github "ArtSabintsev/Siren" "swift3.2" // Swift 3.2
github "ArtSabintsev/Siren" "swift3.1" // Swift 3.1
github "ArtSabintsev/Siren" "swift2.3" // Swift 2.3

Swift Package Manager

.Package(url: "https://github.com/ArtSabintsev/Siren.git", majorVersion: 5)

Implementation Examples

Implementing Siren is as easy as adding two lines of code to your app in either AppDelegate.swift or SceneDelegate.swift:

AppDelegate.swift Example

import Siren // Line 1
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        window?.makeKeyAndVisible()

	Siren.shared.wail() // Line 2

        return true
    }
}

SceneDelegate.swift Example

import Siren // Line 1
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        window?.makeKeyAndVisible()

	Siren.shared.wail() // Line 2

        return true
    }
}

Siren also has plenty of customization options. All examples can be found in the Example Project's AppDelegate file. Uncomment the example you'd like to test.


Device-Specific Checks

Localization

Siren is localized for the following languages:

Arabic, Armenian, Basque, Chinese (Simplified and Traditional), Croatian, Czech, Danish, Dutch, English, Estonian, Finnish, French, German, Greek, Hebrew, Hungarian, Indonesian, Italian, Japanese, Korean, Latvian, Lithuanian, Malay, Norwegian (Bokmål), Persian (Afghanistan, Iran, Persian), Polish, Portuguese (Brazil and Portugal), Romanian, Russian, Serbian (Cyrillic and Latin), Slovenian, Spanish, Swedish, Thai, Turkish, Ukrainian, Urdu, Vietnamese

If your user's device is set to one of the supported locales, an update message will appear in that language. If a locale is not supported, than the message will appear in English.

You may want the update dialog to always appear in a certain language, ignoring the user's device-specific setting. You can enable it like so:

// In this example, we force the `Russian` language.
Siren.shared.presentationManager = PresentationManager(forceLanguageLocalization: .russian)

Device Compatibility

If an app update is available, Siren checks to make sure that the version of iOS on the user's device is compatible with the one that is required by the app update. For example, if a user has iOS 11 installed on their device, but the app update requires iOS 12, an alert will not be shown. This takes care of the false positive case regarding app updating.


Testing

Testing Siren Locally

Temporarily change the version string in Xcode (within the .xcodeproj file) to an older version than the one that's currently available in the App Store. Afterwards, build and run your app, and you should see the alert.

If you currently don't have an app in the store, change your bundleID to one that is already in the store. In the sample app packaged with this library, we use the App Store Connect app's bundleID: com.apple.AppStoreConnect.

Words of Caution

Occasionally, the iTunes JSON will update faster than the App Store CDN, meaning the JSON may state that the new version of the app has been released, while no new binary is made available for download via the App Store. It is for this reason that Siren will, by default, wait 1 day (24 hours) after the JSON has been updated to prompt the user to update. To change the default setting, please modify the value of showAlertAfterCurrentVersionHasBeenReleasedForDays.


App Submission

App Store Review

The App Store reviewer will not see the alert. The version in the App Store will always be older than the version being reviewed.

Phased Releases

In 2017, Apple announced the ability to rollout app updates gradually (a.k.a. Phased Releases). Siren will continue to work as it has in the past, presenting an update modal to all users. If you opt-in to a phased rollout for a specific version, you have a few choices:

  • You can leave Siren configured as normal. Phased rollout will continue to auto-update apps. Since all users can still manually update your app directly from the App Store, Siren will ignore the phased rollout and will prompt users to update.
  • You can set showAlertAfterCurrentVersionHasBeenReleasedForDays to 7, and Siren will not prompt any users until the latest version is 7 days old, after the phased rollout is complete.
  • You can remotely disable Siren until the rollout is done using your own API / backend logic.

Attribution

Special Thanks

A massive shout-out and thank you goes to the following folks:

  • Aaron Brager for motivating me and assisting me in building the initial proof-of-concept of Siren (based on Harpy) back in 2015. Without him, Siren may never have been built.
  • All of Harpy's Contributors for helping building the feature set from 2012-2015 that was used as the basis for the first version of Siren.
  • All of Siren's Contributors for helping make Siren as powerful and bug-free as it currently is today.

Creator

Arthur Ariel Sabintsev

Github

link
Stars: 3422

Dependencies

Used By

Total: 0

Releases

Fix to PresentationManager for certain scenarios - 2020-02-20 04:34:32

#327: Fixed issue around creating specific windows thanks to @giofid

Fixes Scene Issue - 2020-02-11 02:07:59

  • #325: The Siren alert no properly pops up on the first instance of multiscene app (thanks to @kisaha00)

Fixed layering AlertView issue - 2019-10-12 14:01:02

This release should finally fix the iOS 13 issue around layered AlertViews.

Note, that I have not been able to faithfully reproduce this issue, but a couple others have reported that the problem seems to be solved.

This should address: #314, #313, #312, #310, #309, #308

Another attempt to address layering AlertView issue - 2019-10-07 01:23:50

This release attempts to fix the iOS 13 issue around layered AlertViews. I've changed the ordering of the calls for all UIAlertAction, pushing UIWindow cleanup to happen earlier in the sequence.

Note, that I have not been able to faithfully reproduce this issue, so this is a shot in the dark that it will solve this issue.

Closes #312 Closes #310 Closes #309 Closes #308

Reverted hide(window:) method - 2019-09-15 12:34:25

In the conversion to Swift 5.1, I accidentally committed a generic-ized version of this method. The change has been reverted to its previous state.

Adds Swift 5.1 / Xcode 11 / iOS 13 Support - 2019-09-15 03:51:49

This release adds support for Swift 5.1, iOS 13, and Xcode 11. Full updates here: #306

Added Romanian Localization - 2019-09-03 01:21:20

  • #302: Added Romanian localization thanks to @msalirotech

Fixed Support for Swift Package Manager - 2019-08-08 01:54:35

I fixed the Package.swift so that it is now compatible with Xcode 11 and the latest Swift Package Manifest file (// swift-tools-version:4.0).

Fixes Same-Version Update Bug - 2019-05-15 02:15:31

  • #288: It was discovered that Siren would prompt the user with an update if the same version of the app was installed that also happened to be the latest version of the app. This was due to an improper handling of that specific case. This is now fixed in #289. Thanks to @ergunkocak for pointing out this bug!

Fixes to DateExtension - 2019-04-17 01:30:36

#283/#284: Fixes a date calculation mistake on the DateExtension (thanks to @fahlout)

Siren v5 (+ Swift 5 Support) - 2019-03-28 03:44:06

  • Adds Swift 5 Support (#277)
  • Implements Swift 5's Result type in Siren.swift and APIManager.swift
  • Renames LookupModel.swift to APIModel.swift
  • Exposes all values in APIModel.swift in a nice public API on a new struct, Model.swift. (#276)
  • Siren's public completion handler now uses the Result type and returns Model.swift instead of APIModel.swift
  • Fixes the placement of the Update button on .optional alerts (#278)

If you still need access to the Swift 4.2 version of Siren, please use the swift4.2 branch which is equivalent to Siren v4.2.2.

Fixed Imports - 2019-03-11 03:44:09

  • #273: Replaces some Foundation imports with UIKit imports to fix Xcode project generation issues with Bazel. Thanks @thii

Simplified Add/Remove Observer Methods - 2019-02-10 03:53:32

Just some method name changes and code consolidated in Siren.swift around methods dealing with observers. Specific changes can be found here: https://github.com/ArtSabintsev/Siren/commit/df6174ba0645b9b367c7a5896abf96033a3345be#diff-2e790de59976a9805984bb04ac1314d7

Fixed Skip Alert Action Logic - 2019-02-09 01:44:09

  • #270: The skip action had improper conditional logic leading to skip mimicking the next time logic, instead of actually respecting the end-user's preferences. This has now been fixed. (thanks @nixnoughtnothing)

Result Type Changes and Documentation Improvements - 2019-02-02 21:07:36

  • Results.localization is now a let
  • Results.lookupModel is now a let
  • Improved documentation in multiple places and regenerated documentation for https://sabintsev.com/Siren

Multiple Bugfixes and Improvements - 2019-02-02 20:52:49

  • #265 (thanks @erichsu/@belfdev): Adds a new enum, PerformCheck, that is used in the wail method to allow a developer to select if Siren should performa version check when the app enters the foreground state or have it trigger manually when the wail method is called.

  • #267 (thanks @mmdock/@antoinepemeja): Fixes an alert stacking issue when a user uses UpdatePromptFrequency.immediately and the user enters the app switcher before entering the app again.

  • #269 (thanks @mmdock): Adds a new built in version checking and presentation rule

    • Rules(promptFrequency: .weekly, forAlertType: .option)

Fixes "Next Time" Prompt Bug - 2019-01-11 04:51:30

  • #264: Fixes #258 by removing the shouldPerformVersionCheckOnSubsequentLaunch UserDefault. This was done to fix the Next Time action causing the version check alert from appearing every single time a consuming app is launched from the background, irrespective of what rules were in place within RulesManager.

Documentation was also updated.

Quality of Life Bugfixes - 2019-01-06 04:14:09

  • Fixes alerts being layered on top of each other when the consuming app is backgrounded by adding a didEnterBackgroundNotification observer.
  • Changes PresentationManager's alertController variable from private to internal to provide Siren.swift access to this variable. This may get moved into PresentationManager in a future update.
  • Adds missing documentation to wail method.
  • Other minor changes to how code is ordered in Siren.swift

Thanks to @kamrankhan07 for his extensive testing of Siren v4.0.0 and for finding the the alert layering issue.

Siren v4.0.0: Complete Rewrite - 2018-12-27 01:47:27

The latest version of Siren is a complete rewrite of the library.

Tickets like #237 and #190 exposed the inflexibility in the presentation rules of the update alert prompt. Rather than shoehorn this functionality into the existing framework, which was based on Harpy, an Objective-C codebase, I decided to start from scratch.

What's New?

  • New manager-based, unidirectional data flow architecture
  • New rules engine
  • New alert presentation logic
  • Fixed a bug around using the device's default language (rather than English)
  • Fixed rare response-caching bug
  • 100% documentation of all private, fileprivate, internal, and public types using Jazzy.

Tons of example implementations have also been added to the AppDelegate.swift file.

Better Cache Handling - 2018-12-20 22:24:47

  • #254: Improved cache busting on subsequent version checks (thanks to @ivolnov)

Removed old print statement as it wasn't needed - 2018-11-09 18:04:39

#247: Removed print statement from previous feature work (thanks @ilijapuaca)

Siren now maps trackId as an Int again. - 2018-11-08 02:46:14

#246: Apple reverted the change of trackId being returned as a String back to an Int. This release fixes that issue.

Fixed trackId Parsing Issue - 2018-10-26 00:59:33

  • #238/#239: Recently, Apple changed their iTunes Lookup API to return trackId as a String instead of an Int. This is addressed in this version.

Improved Documentation - 2018-09-29 04:04:59

Documentation is now back up at 100%.

Removed Force Unwraps - 2018-09-28 02:26:04

There were a few force unwrapped variables around Bundle and localization. The force unwraps have been removed in favor of better nil handling.

Code Refactor and Bugfix - 2018-09-28 01:50:12

  • Fixed bug where clicking Next Time wasn't being respected between app launches.
  • ShrunkSiren.swift by a few hundred lines of code by move some responsibilities to other files.

Breaking Changes to SirenAlertMessaging - 2018-09-22 19:45:19

#226, #228

Introduced a breaking change toSirenAlertMessaging. Instead of messages of type string, objects of type NSAttributedString need to be passed in. This will allow for further customization of Siren's UIAlertController without having to create a brand new alert.

Swift 4.2's Self Rebinding - 2018-09-19 01:21:29

Minor changes, mostly around making use of Swift 4.2's ability for self rebinding:

guard let self = self else { ... }

Swift 4.2 Support - 2018-09-17 01:50:22

As of Siren v3.5.0, , all future changes on master will be done in Xcode 10 using Swift 4.2.

For those using Swift v4.1.0, please check out the swift4.1 branch or version 3.4.3 - both point to the same commit hash.

Updated German Localization - 2018-07-24 14:03:18

  • #218: Updated German Localization (thanks to @TitouanVanBelle)