Search code examples
swiftnsdatenscalendarnsdatecomponents

Swift: Cannot convert value of type 'NSDate' to expected argument type 'NSDateComponents'


Anyone know how i can solve this? I get this error:

¨cannot convert value of type 'NSDate' to expected argument type 'NSDateComponents'¨ on line:

The error occurred at the line:

let competitionDay = userCalendar.dateFromComponents(competitionDate)!

This is a more complete excerpt of the code:

func Date() {               

    // Here we set the current date

    let date = NSDate()
    let calendar = NSCalendar.currentCalendar()
    let components = calendar.components([.Hour, .Minute, .Second, .Nanosecond], fromDate: date)
    let hour = components.hour
    let minutes = components.minute
    let month = components.month
    let year = components.year
    let day = components.day


    let currentDate = calendar.dateFromComponents(components)



    // here we set the due date. When the timer is supposed to finish
    // final Calendar value

        let userCalendar = NSCalendar.currentCalendar()


        let competitionDate:NSDate = myDatePicker.date


        competitionDate.timeIntervalSinceNow


        let competitionDay = userCalendar.dateFromComponents(competitionDate)!


    // Here we compare the two dates
    competitionDay.timeIntervalSinceDate(currentDate!)


    let dayCalendarUnit = calendar.components([NSCalendarUnit.Day, NSCalendarUnit.Hour, NSCalendarUnit.Minute], fromDate: date)


    //here we change the seconds to hours,minutes and days


    let competitionDayDifference = calendar.components([.Day, .Hour, .Minute],
            fromDate: currentDate!, toDate: competitionDay, options: NSCalendarOptions())

    //finally, here we set the variable to our remaining time
    let daysLeft = competitionDayDifference.day
    let hoursLeft = competitionDayDifference.hour
    let minutesLeft = competitionDayDifference.minute

Solution

  • In your original question you were calling dateFromComponents, which converts a NSDateComponents to a NSDate, but supplied it a competitionDate, which is already a NSDate. And the compiler was simply informing you of this error.

    --

    As an aside, you populate a NSDateComponents with the .Hour, .Minute, .Second, and .Nanosecond from a NSDate, but then proceed to try to save references to the components.year and components.month and components.day even though you didn't specify that those components should be included in the NSDateComponents.

    --

    Below you say:

    It's a Countdown app and i had it running until i wanted a DatePicker to choose the date i am counting down. The competitionDate is the due date

    If that's indeed what you want, then perhaps NSDateComponents isn't needed at all. I'd probably just use NSDateComponentsFormatter method stringFromDate:toDate: to show the user a nice string representation of the amount of time between two NSDate objects.

    For example:

    class ViewController: UIViewController {
    
        @IBOutlet weak var datePicker: UIDatePicker!
        @IBOutlet weak var label: UILabel!
    
        weak var timer: NSTimer?
    
        let formatter: NSDateComponentsFormatter = {
            let _formatter = NSDateComponentsFormatter()
            _formatter.allowedUnits = [.Year, .Month, .Day, .Hour, .Minute, .Second]
            _formatter.unitsStyle = .Full
    
            return _formatter
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            datePicker.date = NSDate().dateByAddingTimeInterval(1000) // initialize it to whatever you want
        }
    
        override func viewDidAppear(animated: Bool) {
            super.viewDidAppear(animated)
    
            timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "didFireTimer:", userInfo: nil, repeats: true)
        }
    
        override func viewDidDisappear(animated: Bool) {
            super.viewDidDisappear(animated)
    
            timer?.invalidate()
        }
    
        func didFireTimer(timer: NSTimer) {
            label.text = formatter.stringFromDate(NSDate(), toDate: datePicker.date)
        }
    }