Showing a welcome screen once per dayData model code review for iOS appShowing a certain screen depending on a particular statusSwitching between view controllers that are loaded in the backgroundQuiz game logicTime manipulation for notification remindersShowing segue after button actionStyling navigationController per viewControllerHandler for a UI to select multiple days of the week for notificationsPresenting and passing data to a modal view controller without using prepare(for:sender:) methodQuiz app with Practice and Exam modes
Overlay of two functions leaves gaps
How much cash can I safely carry into the USA and avoid civil forfeiture?
a sore throat vs a strep throat vs strep throat
Do I have an "anti-research" personality?
What does the integral of a function times a function of a random variable represent, conceptually?
How to limit Drive Letters Windows assigns to new removable USB drives
What term is being referred to with "reflected-sound-of-underground-spirits"?
How do I reattach a shelf to the wall when it ripped out of the wall?
Could the terminal length of components like resistors be reduced?
Like totally amazing interchangeable sister outfits II: The Revenge
How can I practically buy stocks?
Coordinate my way to the name of the (video) game
How to stop co-workers from teasing me because I know Russian?
Why didn't the Space Shuttle bounce back into space as many times as possible so as to lose a lot of kinetic energy up there?
What is the smallest unit of eos?
What causes platform events to fail to be published and should I cater for failed platform event creations?
Re-entry to Germany after vacation using blue card
As an international instructor, should I openly talk about my accent?
Which big number is bigger?
Can't get 5V 3A DC constant
bldc motor, esc and battery draw, nominal vs peak
Is the claim "Employers won't employ people with no 'social media presence'" realistic?
"Whatever a Russian does, they end up making the Kalashnikov gun"? Are there any similar proverbs in English?
Are there physical dangers to preparing a prepared piano?
Showing a welcome screen once per day
Data model code review for iOS appShowing a certain screen depending on a particular statusSwitching between view controllers that are loaded in the backgroundQuiz game logicTime manipulation for notification remindersShowing segue after button actionStyling navigationController per viewControllerHandler for a UI to select multiple days of the week for notificationsPresenting and passing data to a modal view controller without using prepare(for:sender:) methodQuiz app with Practice and Exam modes
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
$begingroup$
I have this method, which first basically shows a Welcome screen to user only once per day. The code I have so far is this
private func showGreetingScreen (tabbar: UITabBarController)
let defaults = UserDefaults.standard
if defaults.object(forKey: "greetingDate") == nil
defaults.set(Date(), forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
else
if let greetingDate = defaults.object(forKey: "greetingDate") as? Date
let order = Calendar.current.compare(Date(), to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(Date(), forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
Now as you can see first I am checking whether Welcome Screen was shown in past or not and then I am saving current date. Then next time app will load, it will compare current date and the date Welcome Screen was shown and based on that It will show Welcome screen to User.
I have feeling that this code can be refactored more.
swift ios
New contributor
Shabir jan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
$endgroup$
add a comment |
$begingroup$
I have this method, which first basically shows a Welcome screen to user only once per day. The code I have so far is this
private func showGreetingScreen (tabbar: UITabBarController)
let defaults = UserDefaults.standard
if defaults.object(forKey: "greetingDate") == nil
defaults.set(Date(), forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
else
if let greetingDate = defaults.object(forKey: "greetingDate") as? Date
let order = Calendar.current.compare(Date(), to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(Date(), forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
Now as you can see first I am checking whether Welcome Screen was shown in past or not and then I am saving current date. Then next time app will load, it will compare current date and the date Welcome Screen was shown and based on that It will show Welcome screen to User.
I have feeling that this code can be refactored more.
swift ios
New contributor
Shabir jan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
$endgroup$
add a comment |
$begingroup$
I have this method, which first basically shows a Welcome screen to user only once per day. The code I have so far is this
private func showGreetingScreen (tabbar: UITabBarController)
let defaults = UserDefaults.standard
if defaults.object(forKey: "greetingDate") == nil
defaults.set(Date(), forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
else
if let greetingDate = defaults.object(forKey: "greetingDate") as? Date
let order = Calendar.current.compare(Date(), to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(Date(), forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
Now as you can see first I am checking whether Welcome Screen was shown in past or not and then I am saving current date. Then next time app will load, it will compare current date and the date Welcome Screen was shown and based on that It will show Welcome screen to User.
I have feeling that this code can be refactored more.
swift ios
New contributor
Shabir jan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
$endgroup$
I have this method, which first basically shows a Welcome screen to user only once per day. The code I have so far is this
private func showGreetingScreen (tabbar: UITabBarController)
let defaults = UserDefaults.standard
if defaults.object(forKey: "greetingDate") == nil
defaults.set(Date(), forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
else
if let greetingDate = defaults.object(forKey: "greetingDate") as? Date
let order = Calendar.current.compare(Date(), to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(Date(), forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
Now as you can see first I am checking whether Welcome Screen was shown in past or not and then I am saving current date. Then next time app will load, it will compare current date and the date Welcome Screen was shown and based on that It will show Welcome screen to User.
I have feeling that this code can be refactored more.
swift ios
swift ios
New contributor
Shabir jan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
Shabir jan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
edited 7 hours ago
Stephen Rauch
3,77061630
3,77061630
New contributor
Shabir jan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
asked 12 hours ago
Shabir janShabir jan
1334
1334
New contributor
Shabir jan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
Shabir jan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
Shabir jan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
$begingroup$
You could rearrange the conditions this way :
if let greetingDate = defaults.object(forKey: "greetingDate") as? Date
let order = Calendar.current.compare(date, to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(date, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
else
defaults.set(date, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)You could extract
Date()as a local variable in this function just in case you are crossing midnight between checks.The parameter name
tabbarin bothshowGreetingScreenandpresentWelcomeScreendoesn't seem necessary, you could use a wild card external name_to avoid being too verbose:private func showGreetingScreen (_ tabbar: UITabBarController)
...
presentWelcomeScreen(tabbar)tabbarisn't used in this function. It is only passed topresentWelcomeScreen, and this calls for refactoring the messaging in your code.Instead of having string literals laying around inside your code, I would prefer to have a struct with all the keys to avoid possible errors:
struct UDKeys
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"Or declare these keys in an extension of
UserDefaultsitself :extension UserDefaults
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"
Finally, your code would look like this :
struct UDKeys
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"
private func showGreetingScreen (_ tabbar: UITabBarController)
let defaults = UserDefaults.standard
let date = Date()
if let greetingDate = defaults.object(forKey: UDKeys.greetingDateKey) as? Date
let order = Calendar.current.compare(date, to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(date, forKey: UDKeys.greetingDateKey)
presentWelcomeScreen(tabbar)
else
defaults.set(date, forKey: UDKeys.greetingDateKey)
presentWelcomeScreen(tabbar)
$endgroup$
add a comment |
$begingroup$
There is some code duplication for the cases “greeting date has never been set” and “last greeting was yesterday or earlier.” This can be avoided if you use the nil-coalescing operator ?? to set the last greeting date to a default value in the past:
let defaults = UserDefaults.standard
let lastGreeting = defaults.object(forKey: "greetingDate") as? Date ?? .distantPast
let now = Date()
if Calendar.current.compare(now, to: lastGreeting, toGranularity: .day) == .orderedDescending
defaults.set(now, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
$endgroup$
add a comment |
$begingroup$
just some other refactoring hints:
- encapsulate the check in a own
UserUsageControllerclass - 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()
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Shabir jan is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f219165%2fshowing-a-welcome-screen-once-per-day%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
You could rearrange the conditions this way :
if let greetingDate = defaults.object(forKey: "greetingDate") as? Date
let order = Calendar.current.compare(date, to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(date, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
else
defaults.set(date, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)You could extract
Date()as a local variable in this function just in case you are crossing midnight between checks.The parameter name
tabbarin bothshowGreetingScreenandpresentWelcomeScreendoesn't seem necessary, you could use a wild card external name_to avoid being too verbose:private func showGreetingScreen (_ tabbar: UITabBarController)
...
presentWelcomeScreen(tabbar)tabbarisn't used in this function. It is only passed topresentWelcomeScreen, and this calls for refactoring the messaging in your code.Instead of having string literals laying around inside your code, I would prefer to have a struct with all the keys to avoid possible errors:
struct UDKeys
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"Or declare these keys in an extension of
UserDefaultsitself :extension UserDefaults
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"
Finally, your code would look like this :
struct UDKeys
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"
private func showGreetingScreen (_ tabbar: UITabBarController)
let defaults = UserDefaults.standard
let date = Date()
if let greetingDate = defaults.object(forKey: UDKeys.greetingDateKey) as? Date
let order = Calendar.current.compare(date, to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(date, forKey: UDKeys.greetingDateKey)
presentWelcomeScreen(tabbar)
else
defaults.set(date, forKey: UDKeys.greetingDateKey)
presentWelcomeScreen(tabbar)
$endgroup$
add a comment |
$begingroup$
You could rearrange the conditions this way :
if let greetingDate = defaults.object(forKey: "greetingDate") as? Date
let order = Calendar.current.compare(date, to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(date, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
else
defaults.set(date, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)You could extract
Date()as a local variable in this function just in case you are crossing midnight between checks.The parameter name
tabbarin bothshowGreetingScreenandpresentWelcomeScreendoesn't seem necessary, you could use a wild card external name_to avoid being too verbose:private func showGreetingScreen (_ tabbar: UITabBarController)
...
presentWelcomeScreen(tabbar)tabbarisn't used in this function. It is only passed topresentWelcomeScreen, and this calls for refactoring the messaging in your code.Instead of having string literals laying around inside your code, I would prefer to have a struct with all the keys to avoid possible errors:
struct UDKeys
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"Or declare these keys in an extension of
UserDefaultsitself :extension UserDefaults
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"
Finally, your code would look like this :
struct UDKeys
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"
private func showGreetingScreen (_ tabbar: UITabBarController)
let defaults = UserDefaults.standard
let date = Date()
if let greetingDate = defaults.object(forKey: UDKeys.greetingDateKey) as? Date
let order = Calendar.current.compare(date, to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(date, forKey: UDKeys.greetingDateKey)
presentWelcomeScreen(tabbar)
else
defaults.set(date, forKey: UDKeys.greetingDateKey)
presentWelcomeScreen(tabbar)
$endgroup$
add a comment |
$begingroup$
You could rearrange the conditions this way :
if let greetingDate = defaults.object(forKey: "greetingDate") as? Date
let order = Calendar.current.compare(date, to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(date, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
else
defaults.set(date, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)You could extract
Date()as a local variable in this function just in case you are crossing midnight between checks.The parameter name
tabbarin bothshowGreetingScreenandpresentWelcomeScreendoesn't seem necessary, you could use a wild card external name_to avoid being too verbose:private func showGreetingScreen (_ tabbar: UITabBarController)
...
presentWelcomeScreen(tabbar)tabbarisn't used in this function. It is only passed topresentWelcomeScreen, and this calls for refactoring the messaging in your code.Instead of having string literals laying around inside your code, I would prefer to have a struct with all the keys to avoid possible errors:
struct UDKeys
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"Or declare these keys in an extension of
UserDefaultsitself :extension UserDefaults
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"
Finally, your code would look like this :
struct UDKeys
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"
private func showGreetingScreen (_ tabbar: UITabBarController)
let defaults = UserDefaults.standard
let date = Date()
if let greetingDate = defaults.object(forKey: UDKeys.greetingDateKey) as? Date
let order = Calendar.current.compare(date, to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(date, forKey: UDKeys.greetingDateKey)
presentWelcomeScreen(tabbar)
else
defaults.set(date, forKey: UDKeys.greetingDateKey)
presentWelcomeScreen(tabbar)
$endgroup$
You could rearrange the conditions this way :
if let greetingDate = defaults.object(forKey: "greetingDate") as? Date
let order = Calendar.current.compare(date, to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(date, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
else
defaults.set(date, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)You could extract
Date()as a local variable in this function just in case you are crossing midnight between checks.The parameter name
tabbarin bothshowGreetingScreenandpresentWelcomeScreendoesn't seem necessary, you could use a wild card external name_to avoid being too verbose:private func showGreetingScreen (_ tabbar: UITabBarController)
...
presentWelcomeScreen(tabbar)tabbarisn't used in this function. It is only passed topresentWelcomeScreen, and this calls for refactoring the messaging in your code.Instead of having string literals laying around inside your code, I would prefer to have a struct with all the keys to avoid possible errors:
struct UDKeys
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"Or declare these keys in an extension of
UserDefaultsitself :extension UserDefaults
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"
Finally, your code would look like this :
struct UDKeys
static let greetingDateKey = "greetingDate"
static let otherKey = "anotherKey"
private func showGreetingScreen (_ tabbar: UITabBarController)
let defaults = UserDefaults.standard
let date = Date()
if let greetingDate = defaults.object(forKey: UDKeys.greetingDateKey) as? Date
let order = Calendar.current.compare(date, to: greetingDate, toGranularity: .day)
if order == .orderedDescending
defaults.set(date, forKey: UDKeys.greetingDateKey)
presentWelcomeScreen(tabbar)
else
defaults.set(date, forKey: UDKeys.greetingDateKey)
presentWelcomeScreen(tabbar)
edited 11 hours ago
answered 11 hours ago
ielyamaniielyamani
437314
437314
add a comment |
add a comment |
$begingroup$
There is some code duplication for the cases “greeting date has never been set” and “last greeting was yesterday or earlier.” This can be avoided if you use the nil-coalescing operator ?? to set the last greeting date to a default value in the past:
let defaults = UserDefaults.standard
let lastGreeting = defaults.object(forKey: "greetingDate") as? Date ?? .distantPast
let now = Date()
if Calendar.current.compare(now, to: lastGreeting, toGranularity: .day) == .orderedDescending
defaults.set(now, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
$endgroup$
add a comment |
$begingroup$
There is some code duplication for the cases “greeting date has never been set” and “last greeting was yesterday or earlier.” This can be avoided if you use the nil-coalescing operator ?? to set the last greeting date to a default value in the past:
let defaults = UserDefaults.standard
let lastGreeting = defaults.object(forKey: "greetingDate") as? Date ?? .distantPast
let now = Date()
if Calendar.current.compare(now, to: lastGreeting, toGranularity: .day) == .orderedDescending
defaults.set(now, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
$endgroup$
add a comment |
$begingroup$
There is some code duplication for the cases “greeting date has never been set” and “last greeting was yesterday or earlier.” This can be avoided if you use the nil-coalescing operator ?? to set the last greeting date to a default value in the past:
let defaults = UserDefaults.standard
let lastGreeting = defaults.object(forKey: "greetingDate") as? Date ?? .distantPast
let now = Date()
if Calendar.current.compare(now, to: lastGreeting, toGranularity: .day) == .orderedDescending
defaults.set(now, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
$endgroup$
There is some code duplication for the cases “greeting date has never been set” and “last greeting was yesterday or earlier.” This can be avoided if you use the nil-coalescing operator ?? to set the last greeting date to a default value in the past:
let defaults = UserDefaults.standard
let lastGreeting = defaults.object(forKey: "greetingDate") as? Date ?? .distantPast
let now = Date()
if Calendar.current.compare(now, to: lastGreeting, toGranularity: .day) == .orderedDescending
defaults.set(now, forKey: "greetingDate")
presentWelcomeScreen(tabbar: tabbar)
answered 8 hours ago
Martin RMartin R
16.3k12366
16.3k12366
add a comment |
add a comment |
$begingroup$
just some other refactoring hints:
- encapsulate the check in a own
UserUsageControllerclass - 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()
$endgroup$
add a comment |
$begingroup$
just some other refactoring hints:
- encapsulate the check in a own
UserUsageControllerclass - 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()
$endgroup$
add a comment |
$begingroup$
just some other refactoring hints:
- encapsulate the check in a own
UserUsageControllerclass - 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()
$endgroup$
just some other refactoring hints:
- encapsulate the check in a own
UserUsageControllerclass - 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()
answered 5 hours ago
mueschamuescha
1865
1865
add a comment |
add a comment |
Shabir jan is a new contributor. Be nice, and check out our Code of Conduct.
Shabir jan is a new contributor. Be nice, and check out our Code of Conduct.
Shabir jan is a new contributor. Be nice, and check out our Code of Conduct.
Shabir jan is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f219165%2fshowing-a-welcome-screen-once-per-day%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown