Get Unix Timestamp that increases by itself - swift

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.

Related

Inout vs pass by reference swift optimization

I have a very large list of numbers and I would like to pass it to a function to do some manipulations to it. Originally, I created a function with an inout property. As many know, inout in swift does NOT pass by reference, rather it makes an initial copy to the function then copies the values back on the return. This sounds expensive. I decided to wrap my list in a class and pass by reference in order to optimize and reduce time for copying. Interestingly enough, it seems that the inout function is faster than the pass by reference function. I even make a manipulation to the inout variable to cause the compiler to copy-on-write. Any ideas why the inout function is faster than the pass by reference?
class ReferencedContainer {
var container = [Int:Bool]()
}
func printTimeElapsedWhenRunningCode(title:String, operation:()->()) {
let startTime = CFAbsoluteTimeGetCurrent()
operation()
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
print("Time elapsed for \(title): \(timeElapsed) s.")
}
func inoutTest(list: inout [Int]?) -> [Int]? {
list![0]=1
return list
}
func refTest(list: ReferencedContainer) -> ReferencedContainer {
list.container[0] = true
return list
}
var list : [Int]? = [Int]()
for i in 0...10000 {
list?.append(i)
}
var ref = ReferencedContainer()
for i in list!
{
ref.container[i] = true
}
printTimeElapsedWhenRunningCode(title: "refTest", operation: { refTest(list: ref)})
printTimeElapsedWhenRunningCode(title: "inout", operation: { inoutTest(list: &list)})
Time elapsed for refTest: 0.0015590190887451172 s.
Time elapsed for inout: 0.00035893917083740234 s.
As many know, inout in swift does NOT pass by reference, rather it makes an initial copy to the function then copies the values back on the return. This sounds expensive.
It's not. It's copying an instance of a [Int: Bool] (a.k.a. Dictionary<Int, Bool>) which is only a single pointer. See for yourself, with print(MemoryLayout<[Int: Bool]>.size).
Two things to consider, out of many possible:
inout may use call-by-reference as an optimisation, see In-Out Parameters
Your two tests are rather different, one uses optionals and an array, the other a dictionary. You're also only testing a single mutation, try doing more. The only difference you should have is struct vs. class and if you try that you can get similar speeds or one of them faster than the other – either way around.

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
}
}

What's the point of READ-only variables when you have LET?

For example:
var dogName : String {
return "Buster"
}
VS..
let dogName = "Buster"
Let's say we're declaring each of these at the top level of a class as instance properties. Are these just two ways of doing the same thing? If not, what's the point of having a read-only variable?
Thanks
Let me try to sum up what the other answers are saying while also adding missing information that I think is critical in order to understand this.
Properties
Properties are simply values that are associated with an object and may be queried in a trivial amount of time without the need (or ability) for parameters like methods have.
Stored Properties
When you create a stored property, whether with let or var, the value assigned at any given point in time will be stored in memory, which is why it is called a stored property.
var name = "Matt"
For variables using var, the value is stored in memory in a way that makes it mutable (editable). You can reassign the value at will and it will replace the previous value stored in memory.
let name = "Matt"
For constants using let, the value is also stored in memory, but in such a way that it may not be changed after the first time assigning to it.
Computed Properties
Computed properties are not stored in memory. As ganzogo says in the comments, computed properties act similarly to methods, but do not take parameters. When deciding when to use a computed property or a function with no parameters, the Swift API Design Guidelines recommend using a computed property when it will simply create or fetch, and then return the value, provided that this takes a trivial amount of time.
var fullName: String {
return firstName + lastName
}
Here, we assume that firstName and lastName are already properties on the object. There is no sense of initialization with this property because it is not stored anywhere. It is fetched on demand every time. That is why there is no sense to doing anything like the following:
var dogName : String {
return "Buster"
}
This has no benefit over a stored property except that no memory will be used in storing the String "Buster".
In fact, this is a simplified version of computed properties. You will notice that the Swift Language Guide describes the use of both get and set in a computed property. set allows you to update the state of other variables when one sets a computed variable. For example:
var stored: Int
var computed: Int {
get {
return stored + 5
}
set {
stored = newValue - 5
}
}
Some useful applications of this were pointed out by Rajan's answer, for example getting and setting volume from width, height, and depth.
A read-only computed var is just a computed var which specifies only a getter, in which case the get keyword and brackets are not required.
Read-Only for Access Control
When developing modules such as frameworks, it is often useful to have a variable only be modifiable from within that object or framework and have it be read-only to the public.
private var modifiableItem: String
public var item: String {
return modifiableItem
}
The idea here is that modifiableItem should only be mutable from within the object that defined it. The private keyword ensures that it is only accessible within the scope of the object that created it and making it a var ensures that it may be modified. The public var item, then, is a computed variable that is exposed to the public that enables anyone to read, but not mutate the variable.
As Hamish notes in the comments, this is more concisely expressible by using private(set):
public private(set) var item: String
This is probably the best way to go about it, but the previous code (using a private stored property and public computed one) demonstrates the effect.
let dogName = "Buster"
means that the dogName variable can't be changed later on once assigned "Buster" and it becomes constant
var dogName : String {
return "Buster"
}
It is a computed read only property where you can have some calculation which can be changed as it is a var but in a way defined below:
The computed property can be changed like
var dogName : String {
return "Stress"+"Buster"
}
Consider this example from Apple Docs
struct Cuboid {
var width = 0.0, height = 0.0, depth = 0.0
var volume: Double {
return width * height * depth
}
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
It will print
// Prints "the volume of fourByFiveByTwo is 40.0"
Here the volume is calculated when you initialize the object of struct Cuboid and is computed at run time. If it was let, then you have to initialize it before using by some constant.
If you want to read more about it, read the Computed Properties section here
In your example, they are 2 ways of doing the same thing. However, you can do a lot more with a computed property. For example:
var dogName: String {
return firstName + " " + lastName
}
Here, firstName and lastName might not be known at initialization time. This is not possible to do with a simple let property.
It might help you to think of a computed property as a method with no parameters.
A read-only property in a class/struct means that you can't change the value of the property for that instance of the class/struct. It prevents me from doing:
someObject.dogName = "Buddy" // This fails - read-only property
However, I can still do this:
var someVariable = someObject.dogName // someVariable now is "Buster"
someVariable = "Buddy" // This is OK, it's now "Buddy"
A let constant means you won't be changing the value of that specific constant in that block of code.
let someName = "Buster"
someName = "Buddy" // This fails - someName is a constant
There are two different cases:
1) Value type:
struct DogValueType {
var name: String
}
let dog1 = DogValueType(name: "Buster")
var dog2: DogValueType {
return DogValueType(name: "Buster")
}
let dog3: DogValueType = {
return DogValueType(name: "Buster")
}()
dog1 - dog3 can't be changed or mutated
dog1 & dog3 stores value
dog3 computes value each time you accessing it
2) Reference type:
class DogReferenceType {
var name: String
init(name: String) {
self.name = name
}
}
let dog4 = DogReferenceType(name: "Buster")
var dog5: DogReferenceType {
return DogReferenceType(name: "Buster")
}
let dog6: DogReferenceType = {
return DogReferenceType(name: "Buster")
}()
dog4 - dog6 can't be changed, but can be mutated
dog4 & dog6 stores reference to an object.
dog5 creates object each time you accessing it

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.

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

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.