Using customized setter/getter and initializing the property for a swift date - swift

I have a class called Trip which has an NSDate property called date. My desire is to make sure that the date property always has the time value set to the beginning of the day. I do this by:
Creating an NSCalendar constant called calendar so that I can use the startOfDayForDate method to reset the date value.
Creating a custom setter method for the date property that calls the startOfDayForDate method.
However, I want to initialize the date property to the start of today's date.
The code that I have so far is shown below.
class Trip {
private let calendar: NSCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
var date: NSDate {
get {
return self.date
}
set {
self.date = calendar.startOfDayForDate(newValue)
}
}
}
This code a) doesn't initialize the date property and b) (I discovered) results in an infinite loop when the setter is called. Upon further research, I believe that customized getters/setters are strictly computed, right?
How do I accomplish what I mentioned earlier:
a.) making sure that sets to the date property reset to the start of the day and
b.) initializing the date property to the start of today's date?

I think you want to have a date that will always be the start of the date. Replace your current date variable with this:
private var privateDate = NSDate()
var date: NSDate {
get {
return privateDate
}
set {
privateDate = calendar.startOfDayForDate(newValue)
}
}
There may be a slightly better way to do this, but I'm guessing your application won't have tens of thousands of your Trip class, so you should be fine.

Related

Get Unix Timestamp that increases by itself

So basically what I'd like to do is have a date object
let unixTime = Date().timeIntervalSince1970.advanced(by: -30)
and have unixTime change as the seconds pass so that unixTime is offset from the current time without me having to increase the value myself. Is there a way to do that in Swift?
Instead of declaring unixTime as a constant, declare it as a computed variable.
For example, if this code is part of a struct or class, I'd do this:
struct Test {
var unixTime: Date {
Date().timeIntervalSince1970.advanced(by: -30)
}
func tion() {
//do stuff
}
...
}
If you need it in an imperative context (such as a script) or you don't want to clutter the namespace of your type, you can declare it locally:
...
doStuff()
var unixTime: Date {
Date().timeIntervalSince1970.advanced(by: -30)
}
...
Either way, you can refer to it in the same way as you are doing now, but it will be recomputed every time.

CMLogItem timestamp: Why so complicated?

I receive a CMLogItem from a CoreMotion query in swift (could be accelerometer, gyroscope). Now, I want to get the timestamp of that sample, preferably as a Date() object. CMLogItems have a property .timestamp of type TimeInterval.
The documentation tells me the following:
The CMLogItem class defines a read-only timestamp property that
records the time a motion-event measurement was taken.
However, I am not sure how to convert this timestamp to a Date() object because I dont know what the timestamp is referring to.
Another documentation says:
The timestamp is the amount of time in seconds since the device
booted.
But this seems really weird and I dont understand why apple would create such an inconsistent and complicated API.
Proper answer is:
extension CMLogItem {
static let bootTime = Date(timeIntervalSinceNow: -ProcessInfo.processInfo.systemUptime)
func startTime() -> Date {
return CMLogItem.bootTime.addingTimeInterval(self.timestamp)
}
}
This gives us stable, monotonic results, which is not a case, when bootTime is computed every time startTime is called.
I think I figured it out.
The documentation is just wrong here.
It is not the "time in seconds since the device booted" — it is indeed the time since their reference date.
Fix:
extension CMLogItem {
func startTime() -> Date {
#if os(watchOS)
return Date(timeIntervalSinceReferenceDate: self.timestamp)
#else
let systemRebootTime = Date(timeIntervalSinceNow: -ProcessInfo.processInfo.systemUptime)
return systemRebootTime.addingTimeInterval(self.timestamp)
#endif
}
}

NSCalendar.startOfDayForDate(date:) equivalent for iOS 7 with non-optional return type

Is it possible to change an NSDate object so that the result is equivalent to NSCalendar.startOfDayForDate(date:)? That method is only available to iOS 8 and newer, but I am looking for something that works on iOS 7.
I have looked at two methods:
NSCalendar.dateFromComponents(comps:) as described here: NSDate beginning of day and end of day. For instance, like this:
class func startOfDay(date: NSDate, calendar: NSCalendar) -> NSDate {
if #available(iOS 8, *) {
return calendar.startOfDayForDate(date)
} else {
let dateComponents = calendar.components([.Year, .Month, .Day], fromDate: date)
return calendar.dateFromComponents(dateComponents)!
}
}
NSDateFormatter.dateFromString(string:) by way of
stringFromDate(date:), i.e. converting the NSDate object into a string without the time, then converting it back into an NSDate object.
The problem with both methods is that they return an optional NSDate. I am reluctant to unwrap this implicitly and I’d rather avoid changing the return type of the method within which these methods are called.
I think the calendar.components() method returns an optional, because you can theoretically enter components that do not create valid date, like 2000-02-30. If, as in your case, the components already come from a valid date, I would not be reluctant to implicitly unwrap the optional.

In Swift what exactly is the difference between a function that returns a value and one that does not?

Here is some code that I am using in my program
func getDate() {
getTimeRightNow()
date = timeRightNow
sendDate()
print("date was sent")
}
func getTimeRightNow() {
timeRightNow = NSDate().timeIntervalSince1970
}
The function getDate() calls getTimeRightNow() which then gets the current NSDate and sets it equal to a variable timeRightNow. I then take timeRightNow and set date equal to it which I then pass along for further use.
Below, I have a second version. This time I instead have the getTimeRightNow() function return a value of type Double...
func getDate() {
date = getTimeRightNow()
sendDate()
print("date was sent")
}
func getTimeRightNow()-> Double {
timeRightNow = NSDate().timeIntervalSince1970
return timeRightNow
}
Both versions seems to work exactly the same. I guess the second version lets me type one less line, is that the only advantage that it offers? Is the second version considered "best practice"? In the second version, is there any chance that the sendDate() function gets called BEFORE the getTimeRightNow() function finishes and sets a value for date? How about in the first version, is there any chance that timeRightNow gets set equal to date BEFORE the getTimeRightNow() function finishes and sets a proper NSDate for timeRightNow?
Having trouble understanding this, appreciate the help
The difference between the function that has a return value and one that does not is that it returns a value. That can be really practical.
let aDate = myRandomDate()
let anotherDate = myRandomDate()
You would not be able to do this with a function that does not return a value.

Check to see if NSDate holds a date or is empty

What would be the best way to see if an NSDate is actually set to a date or is empty? Returning its description or changing it to string returns "(null)"...?
Thanks.
If you want to see if an instance of NSDate (or any object) is nil, just compare it to nil. A non-null NSDate object will never be empty; it always contains a date. Both -init and +date return an NSDate object initialized to the current date and time, and there is no other way to create an instance of this class.
if(someData == nil) {
// do stuff
}
if it doesn't hold a date, then you have a nil pointer, so simply
if (!date) {
...
}
or more explicitly
if (date == nil) {
...
}