Skip to content

Instantly share code, notes, and snippets.

@danhalliday
Last active June 1, 2023 07:25
Show Gist options
  • Save danhalliday/e83f7526b20ca01f44ac15e351c46cad to your computer and use it in GitHub Desktop.
Save danhalliday/e83f7526b20ca01f44ac15e351c46cad to your computer and use it in GitHub Desktop.
iOS First Launch Helper
import Foundation
/// Registers how many times an app has been launched, using UserDefaults as storage.
class LaunchCounter {
private var defaults: UserDefaults
private var defaultsKey = "launchCount"
/// Initialise, optionally with a custom UserDefaults instance
init(defaults: UserDefaults = .standard) {
self.defaults = defaults
}
/// The number of times the app has launched
var launchCount: Int {
get { return defaults.integer(forKey: defaultsKey) }
set { defaults.set(newValue, forKey: defaultsKey) }
}
/// True if this is the first time the app has launched
var isFirstLaunch: Bool {
return launchCount == 1
}
/// Register an app launch. Call before any other methods, and call only once.
func registerLaunch() {
launchCount += 1
}
}
import XCTest
@testable import App
class LaunchCounterTests: XCTestCase {
let launchCounter = LaunchCounter(defaults: MockUserDefaults())
func testLaunchCounter() {
XCTAssert(launchCounter.launchCount == 0, "Identify never launched")
XCTAssert(launchCounter.isFirstLaunch == false, "Don't identify never launched as first")
launchCounter.registerLaunch()
XCTAssert(launchCounter.isFirstLaunch == true, "Identify first launch")
launchCounter.registerLaunch()
XCTAssert(launchCounter.launchCount == 2, "Identify second launch")
XCTAssert(launchCounter.isFirstLaunch == false, "Don't identify second launch as first")
let randomCount = Int(arc4random_uniform(100) + 1)
(0..<randomCount).forEach { _ in launchCounter.registerLaunch() }
XCTAssert(launchCounter.launchCount == 2 + randomCount, "Identify Nth launch")
XCTAssert(launchCounter.isFirstLaunch == false, "Don't identify Nth launch as first")
}
}
import Foundation
class MockUserDefaults: UserDefaults {
var storage: [String:Any] = [:]
override func object(forKey defaultName: String) -> Any? {
return storage[defaultName]
}
override func set(_ value: Any?, forKey defaultName: String) {
storage[defaultName] = value
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment