just some other refactoring hints:
- encapsulate the check in a own
UserUsageController
class
- then you can test it better
- maybe the check for midnight is dependend on timezone?
user returning over time zone:
- show the welcome screen also if the last visit longer then a 8 hours - maybe user comes there at 23:00 and again at 02:00 - then it also not make sense to show the welcome screen
short time user:
- maybe only set the lastVisitDate if the user has used the app more then 2 minutes (for example if he enter the app because he accidently tap on a push notification)
- or set the last visit date only when the user exits the welcome screen
sample implementation (thanks to @Martin-R for code deduplication):
import UIKit
class UserUsageController {
static let greetingDateKey = "greetingDate"
static func isReturning(now: Date = Date(), minHours: Int = 8) -> Bool {
let lastGreeting = getLastVisit() ?? .distantPast
let dayBefore = isDayBefore(now: now, last: lastGreeting)
let leastTime = isLeastTime(now: now, last: lastGreeting, minHours: minHours)
return dayBefore && leastTime
}
private static func isDayBefore(now: Date, last: Date) -> Bool {
return Calendar.current.compare(now, to: last, toGranularity: .day) == .orderedDescending
}
private static func isLeastTime(now: Date, last: Date, minHours: Int) -> Bool {
let hours = Calendar.current.dateComponents([.hour], from: last, to: now ).hour ?? 0
return hours > minHours
}
static func setLastVisit(date: Date = Date()){
UserDefaults.standard.set(date, forKey: greetingDateKey)
}
static func getLastVisit() -> Date? {
return UserDefaults.standard.object(forKey: greetingDateKey) as? Date
}
}
Tests:
let df = DateFormatter()
df.dateFormat = "yyyy/MM/dd HH:mm"
UserUsageController.setLastVisit(date: df.date(from: "2019/04/20 01:00")! )
assert(false == UserUsageController.isReturning(now: df.date(from: "2019/04/20 09:00")!))
assert(false == UserUsageController.isReturning(now: df.date(from: "2019/04/20 23:00")!))
UserUsageController.setLastVisit(date: df.date(from: "2019/04/20 22:00")! )
assert(false == UserUsageController.isReturning(now: df.date(from: "2019/04/21 01:00")!))
assert(true == UserUsageController.isReturning(now: df.date(from: "2019/04/21 01:00")!,
minHours: 1))
assert(false == UserUsageController.isReturning(now: df.date(from: "2019/04/21 06:59")!))
assert(true == UserUsageController.isReturning(now: df.date(from: "2019/04/21 07:00")!))
assert(true == UserUsageController.isReturning(now: df.date(from: "2019/04/21 08:00")!))
assert(true == UserUsageController.isReturning(now: df.date(from: "2019/04/22 08:00")!))
Usage:
// in calling class
if UserUsageController.isReturning() {
// OpenWelcomeScreen
}
// onClose at welcomeScreen
UserUsageController.setLastVisit()