Reputation: 1946
I'm having a strange bug where my application will crash on all simulators less than the iPhone 5s.
Firstly, I've tried resetting all the simulators and the crash still persists.
extension NSDate {
func firstDayOfMonth() -> NSDate {
let cal = NSCalendar.currentCalendar()
let comp = cal.components([.Year, .Month], fromDate: self)
// to 12pm
comp.hour = 12
comp.minute = 0
comp.second = 0
return cal.dateFromComponents(comp)!
}
func lastDayOfMonth() -> NSDate {
let cal = NSCalendar.currentCalendar()
let comp = NSDateComponents()
comp.month = 1
comp.day -= 1
// to 12pm
comp.hour = 12
comp.minute = 0
comp.second = 0
return cal.dateByAddingComponents(comp, toDate: self.firstDayOfMonth()!, options: [])!
}
}
The final line of code in the second function:
cal.dateByAddingComponents(comp, toDate: self.firstDayOfMonth()!, options: [])!
returns 5828963-12-20 00:00:00 +0000
on the devices where the crash occurs.
I'm able to consistently reproduce the issue when running on the iPhone 4s (v8.4, v9.3) and iPhone 5 (v8.4, v9.3) however the error does not occur in the playground or on the iPhone 5s or iPhone 6/6s
Any help would be much appreciated.
Upvotes: 3
Views: 230
Reputation: 285220
Please try this alternative date math
extension NSDate {
func firstDayOfMonth() -> NSDate {
let calendar = NSCalendar.currentCalendar()
var startDate : NSDate?
calendar.rangeOfUnit(.Month, startDate: &startDate, interval: nil, forDate: self)
let components = calendar.components([.Year, .Month, .Day], fromDate: startDate!)
components.hour = 12
return calendar.dateFromComponents(components)!
}
func lastDayOfMonth() -> NSDate {
let calendar = NSCalendar.currentCalendar()
let dayRange = calendar.rangeOfUnit(.Day, inUnit: .Month, forDate: self)
let dayLength = dayRange.length
let components = calendar.components([.Year, .Month, .Day], fromDate: self)
components.day = dayLength
components.hour = 12
return calendar.dateFromComponents(components)!
}
}
Swift 3
extension Date {
func firstDateOfMonth() -> Date {
let calendar = Calendar.current
var startDate = Date()
var interval : TimeInterval = 0
_ = calendar.dateInterval(of:.month, start: &startDate, interval: &interval, for: self)
return startDate
}
func lastDateOfMonth() -> Date {
let calendar = Calendar.current
let dayRange = calendar.range(of:.day, in: .month, for: self)!
let dayLength = dayRange.upperBound
var components = calendar.dateComponents([.year, .month, .day], from: self)
components.day = dayLength
return calendar.date(from:components)!
}
}
Setting the hour to 12 can be useful especially in Brasil where one of the daylight saving dates skips 0:00 to 0:59.
Upvotes: 2
Reputation: 5974
This could be happening because of an Integer overflow. iPhone 5s
and above use 64-bit
processors where as below ones use 32-bit
. Do check this apple documentation regarding finding out diffrence between days using dateFromComponents
..
From apple documentation...
Do not use this method for comparing second differences because it overflows NSInteger on 32-bit platforms.
Possible solution to avoid the crash
Upvotes: 1