0

In my program, i have a "reset" button that i want to make appear when the user opens the app for the first time each day. So When the view loads, i create a variable to hold what day it is (i.e: 19), and then set that day as a user default. I then use an if statement to determine whether the user default is equal to the actual day it is. I'm not able to get the hiding and unhiding of the "reset" button completely figured out.

Here is the code i have so far. Im new to swift, so any advice or feedback on my approach would be greatly appreciated! Thanks

class UserInfoViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

   let date = Date()
   let calendar = Calendar.current


   let dateToday = calendar.component(.day, from: date)
   let dateToCompare = calendar.component(.day , from: date)

   UserDefaults.standard.set(dateToday, forKey: "userDefaultDate")

   let userDefaultDate = UserDefaults.standard.value(forKey: self.userDefaultDate) as? Int


    if userDefaultDate != dateToCompare {

        resetLabel.isHidden = false
        UserDefaults.standard.set(dateToCompare, forKey: "userDefaultDate")

    }

    if userDefaultDate == dateToCompare {

        resetLabel.isHidden = true
    }
}
t4nhpt
  • 5,264
  • 4
  • 34
  • 43
  • Follows link: https://stackoverflow.com/questions/39018335/swift-3-comparing-date-objects – Sagar Chauhan Mar 19 '18 at 08:05
  • 1
    What is `self.userDefaultDate`? There are at least 3 stuff named "userDefaultDate" – t4nhpt Mar 19 '18 at 08:08
  • That is the key for the user default. I was thinking i need to use a default to save the day each time a user loads the app. That way i can check to see if it is the users first time checking the app for today, and if it is - i want to make the "reset data" button visible – Coding while Loading Mar 19 '18 at 08:10
  • You can not compare two dates like `userDefaultDate != dateToCompare`. Use `compare` instead. Example: `date1.compare(date2) == ComparisonResult.orderedDescending`. – TheTiger Mar 19 '18 at 08:11
  • @TheTiger Of course you can. Dates in Swift are `Comparable`. – Sulthan Mar 19 '18 at 08:12
  • @Sulthan Oh thanks! I will check. – TheTiger Mar 19 '18 at 08:13
  • 1
    @CodingwhileLoading BTW to check if the date is today `Calendar.current.isDateInToday(date1)` – TheTiger Mar 19 '18 at 08:14
  • *Note:* Saving a day in `userDefaults` and then comparing with a day component will work only for same month. – TheTiger Mar 19 '18 at 08:27

5 Answers5

3

Your code cannot work.

The logic is supposed to be:

  • Get the day from UserDefaults,
  • Compare it to the current day.
  • If the values are not equal save the new day to UserDefaults

class UserInfoViewController: UIViewController {

    override func viewDidLoad() {
       super.viewDidLoad()

       let dateToday = Calendar.current.component(.day, from: Date())
       let dateToCompare = UserDefaults.standard.integer(forKey: "userDefaultDate")
       if dateToCompare != dateToCompare {
           UserDefaults.standard.set(dateToday, forKey: "userDefaultDate")
           resetLabel.isHidden = false
        } else {
           resetLabel.isHidden = true
        }
    }
}

Note:

Never use value(forKey: with UserDefaults.
There are many convenience methods and for objects use object(forKey:

Edit

It's more reliable to save the Date object and compare using isDateInToday of Calendar

class UserInfoViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let dateToday = Date()
        let calendar = Calendar.current
        let dateToCompare = UserDefaults.standard.object(forKey: "userDefaultDate") as? Date ?? Date.distantPast
        if calendar.isDateInToday(dateToCompare) {
            resetLabel.isHidden = true
        } else {
            UserDefaults.standard.set(dateToday, forKey: "userDefaultDate")
            resetLabel.isHidden = false
        }
    }
}
vadian
  • 274,689
  • 30
  • 353
  • 361
  • I translated your response into "minutes" so that i can test it out now, however, after 1 minute passes i still do not get the "Reset" button to be unhidden. here is translated let firstMinute = Calendar.current.component(.minute, from: Date()) let minuteToCompare = UserDefaults.standard.integer(forKey: "defaultMinute") if minuteToCompare != minuteToCompare { UserDefaults.standard.set(firstMinute, forKey: "defaultMinute") resetLabel.isHidden = false } else { resetLabel.isHidden = true } – Coding while Loading Mar 19 '18 at 08:34
  • let firstMinute = Calendar.current.component(.minute, from: Date()) let minuteToCompare = UserDefaults.standard.integer(forKey: "defaultMinute") if minuteToCompare != minuteToCompare { UserDefaults.standard.set(firstMinute, forKey: "defaultMinute") resetLabel.isHidden = false } else { resetLabel.isHidden = true } – Coding while Loading Mar 19 '18 at 08:34
  • `minuteToCompare != minuteToCompare` is wrong. It's always equal. It must be `firstMinute != minuteToCompare` – vadian Mar 19 '18 at 08:41
  • You are totally right! it works on a minute to minute basis! so it should work on a day to day basis.. thank you kindly! 2 questions- should i implement your edit instead - where i save the date object? and last question - is there a way to the button invisible again after the user clicks it for the first time ? Thank you- i am a beginner at swift and your logic is helping me learn and understand – Coding while Loading Mar 19 '18 at 08:47
  • I suggested the edit because if the user opens the app on 3/19 and then the next time on 4/19 the days are the same. Regarding your second question: I guess it is. You need to keep the state whether the user has clicked the first time. – vadian Mar 19 '18 at 08:52
0

Let me modify your code:

class UserInfoViewController: UIViewController {
let userDefaultDate = "userDefaultDate"

override func viewDidLoad() {
    super.viewDidLoad()

    let date = Date()
    let calendar = Calendar.current
    let dateToCompare = calendar.component(.day , from: date)

    let userDefaultDate = UserDefaults.standard.integer(forKey: "userDefaultDate")

    if userDefaultDate != dateToCompare {
        resetLabel.isHidden = false
        UserDefaults.standard.set(dateToCompare, forKey: self.userDefaultDate)
    } else {
        resetLabel.isHidden = true
    }
}

What you are wrong is that you set the value the user default before you check. So your comparison is always equal. This line I mean: UserDefaults.standard.set(dateToday, forKey: "userDefaultDate")

t4nhpt
  • 5,264
  • 4
  • 34
  • 43
0

try this, hope will help you.

override func viewDidLoad() {
    super.viewDidLoad()
            let date = Date()
            let calendar = Calendar.current


            let dateToday = calendar.component(.day, from: date)
            let dateToCompare = Int(calendar.component(.day , from: date))

            UserDefaults.standard.set(dateToday, forKey: "userDefaultDate")

            let userDefaultDate = UserDefaults.standard.value(forKey: "userDefaultDate") as? Int


            if userDefaultDate != dateToCompare {
                UserDefaults.standard.set(dateToCompare, forKey: "userDefaultDate")
                resetLabel.isHidden = true

            } else {
                resetLabel.isHidden = true
            }
}   

in this code if userDefaultDate != dateToCompare, dateToCompare save in UserDefaults and hide you resetLabel, else if userDefaultDate = dateToCompare, its simply hide you resetLabel
but if you need show resetLabel if userDefaultDate != dateToCompare you will change this one:

UserDefaults.standard.set(dateToCompare, forKey: "userDefaultDate")
resetLabel.isHidden = false
Sergey Hleb
  • 152
  • 1
  • 16
  • Why another comparison in the `else` clause? If `userDefaultDate != dateToCompare` is evaluated to `false` the values **are** equal. And your logic doesn't work either. – vadian Mar 19 '18 at 08:22
  • There are only two cases one can be equal or second not equal. `else if` is useless here. – TheTiger Mar 19 '18 at 08:22
  • In both cases you are hiding the `resetLabel`. – TheTiger Mar 19 '18 at 08:25
  • @vadian, sorry, sometimes have more then 2 comparisons – Sergey Hleb Mar 19 '18 at 08:27
  • @TheTiger, The point is to hide resetLabel when the dates coincide, and if we keep the current date, which is exactly equal to the date for comparison, why do we need a resetLabel? – Sergey Hleb Mar 19 '18 at 08:30
  • @SergeyHleb In `if` and `else` you are doing same thing. So comparison is becoming useless here. You can write `resetLabel.isHidden = true` outside the comparison. – TheTiger Mar 19 '18 at 08:32
  • @TheTiger, if I correctly understood the question, it is necessary to compare the current date with the saved one, if it coincide, then hide the resetLabel. when the dates are different, we save the current one, which means that the dates will coincide, and by the condition if the dates coincide - we hide the resetLabel – Sergey Hleb Mar 19 '18 at 08:38
0

You will not be able to achieve your requirement as dateToday & dateToCompare will always be equal. Also you might want to use a button instead of a label(resetLabel) if you want a button action.

Try this code:

    override func viewDidLoad() {
    super.viewDidLoad()

    let presentDate = Date()

    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "dd/mm/yyyy"
    let dateString = dateFormatter.string(from: presentDate)

    guard let userDefaultDate = UserDefaults.standard.object(forKey: "userDefaultDate") as? String else {
        UserDefaults.standard.set(dateString, forKey: "userDefaultDate") //this line would be executed when you are setting the date for the first time, i.e on your first app launch.
        resetLabel.isHidden = true
        return
    }

    if userDefaultDate != dateString {
        resetLabel.isHidden = false
        UserDefaults.standard.set(dateString, forKey: "userDefaultDate")
    } else {
        resetLabel.isHidden = true
    }
}

Here I'm converting the date into a string in the format dd/mm/yyyy and saving it in the UserDefaults

chakkala
  • 63
  • 10
0

Using Calendar API implementation:

Calendar.current.isDateInToday(dateToCompare)

Another Simple approach Using Swift Compare API:

func twoDatesAreSame(date1: Date, date2: Date) -> Bool {
    
    let dateCompared = Calendar.current.compare(date1, to: date2, toGranularity: .day)
    
    switch dateCompared {
    case .orderedAscending:
        //date1 is earlier than date2, when compared at the specified level of precision
        return false
    case .orderedDescending:
        //date1 is later than date2, when compared at the specified level of precision
        return false
    case .orderedSame:
        //date1 is equal to date2, when compared at the specified level of precision
        return true
    }
}
Mr.SwiftOak
  • 1,469
  • 3
  • 8
  • 19