I have an Onboarding controller, when a user has completed Onboarding I am writing a value in UserDefaults
and then dismissing the OnboardingViewController.
My base viewcontroller however is pushing them back to the Onboarding flow as UserDefaults.standard.bool(forKey: "ONBOARDING|COMPLETE")
is returning false.
If I restart my app however is will return true and they are pushed to the correct VC.
My Base ViewController
class ViewController: UIViewController {
var onboardingComplete: Bool {
get {
return UserDefaults.standard.bool(forKey: "ONBOARDING|COMPLETE")
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print(UserDefaults.standard.bool(forKey: "ONBOARDING|COMPLETE"))
print(onboardingComplete)
setBaseViewController()
}
fileprivate func setBaseViewController() {
if onboardingComplete {
print("has completed onboarding")
} else {
let layout = UICollectionViewFlowLayout()
navigationController?.present(OnboardingController(collectionViewLayout: layout), animated: true, completion: { })
}
}
}
My Onboarding controller has a method in which I am using to set the value as complete
@objc func handleCompleteOnboarding() {
dismiss(animated: true) {
DispatchQueue.main.async {
UserDefaults.standard.set(true, forKey: "ONBOARDING|COMPLETE")
}
}
}
You are setting the value in the completion handler.
Move this outside of dismiss.
@objc func handleCompleteOnboarding() {
UserDefaults.standard.set(true, forKey: "ONBOARDING|COMPLETE")
dismiss(animated: true)
}
You have essentially created a race condition between you setting the value and your viewDidAppear
method being called.