-1

I'm trying to create a var without assigning a value when it's initialized. I'm new to swift, coming from Objective-c, and I'm having trouble using the wrapper/unwrapper. I have the following in my code:

var elapsedTime : NSTimeInterval!

self.elapsedTime -= (NSTimeInterval(hours) * 3600)

I get the following error at the second line:

Binary operator '-=' cannot be applied to operands of type 'NSTimeInterval!' and '(Double)'

What should I do to fix that, and why am I getting an error?

Horay
  • 1,388
  • 2
  • 19
  • 36

2 Answers2

1

It's a behavior specific to the implicitly unwrapped optional. The ! after the name of the type makes it an implictly unwrapped optional, for instance with NSTimeInterval!. The compiler will let you try and access the value inside the optional without checking for nil. If there is a nil there at runtime, your program will explode.

For some reason, -= can't be applied with the implicitly unwrapped optional on the left. NSTimeInterval is a typealias for Double, so I'm going to use a simple example.

var time = 0.0
var dangerousTime: Double! = 15.0
time -= dangerousTime // works fine
dangerousTime = dangerousTime - time // works fine
dangerousTime -= time // errors out

Implicitly unwrapped optionals are dangerous and you should avoid using them. This will probably fix your problem anyway. A few possible ways to go from here:

In Swift, you don't need an Optional to declare a variable without initialization. The compiler just won't let you use it until you've assigned it an initial value.

var time: Double
var foo = time + 5 // error
time = 4.0
foo = time + 5 // success

What you may want is a regular old Optional and a safe syntax for using the Optional.

var maybeTime: Double?
if let time = maybeTime {
    maybeTime = time - 42
}
Rikki Gibson
  • 4,136
  • 23
  • 34
  • Should I use `self` when I access it? – Horay Aug 20 '15 at 17:22
  • "self" is just an identifier that is available in an instance method on a class or struct. You can access an instance variable inside an instance method without explicitly using self. If you're in a static method or a top level function, there is no self. It's a bit of a matter of personal style. However, if you pass an instance member to a closure, the compiler will require you use self to access it. – Rikki Gibson Aug 20 '15 at 17:33
  • Thanks for the explanation and the AMAZING answer! When I try creating a the `var elapsedTime : NSTimeInterval` (even without using it in the code at all) I get an error at the class name: `Class 'myClassName' has not initializers` – Horay Aug 20 '15 at 17:59
  • More context is needed. Edit your question or create a new question with a minimal, complete, and verifiable example. http://stackoverflow.com/help/mcve – Rikki Gibson Aug 20 '15 at 21:01
  • Thanks for the answer! I have a different problem now. I you're able to please answer it, I'd greatly appreciate it! http://stackoverflow.com/questions/32127138/how-to-add-5-seconds-to-a-timer\ – Horay Aug 20 '15 at 21:03
0

You may have run into a compiler bug.

elapsedTime is declared as an Optional, which means that it may have a value, like zero, or it may have no value.

The -= operator only has meaning when elapsedTime has a value.

If you want to handle the case where elapsedTime has no value, you can do something like this:

if let elapsedTime = self.elapsedTime {
    self.elapsedTime = elapsedTime - (NSTimeInterval(hours) * 3600)
}
else {
    // self.elapsedTime has no value.  What do you want to do?
}

If you just want to assume that self.elapsedTime always has a value, you can do this:

    let elapsedTime : NSTimeInterval = self.elapsedTime
    self.elapsedTime = elapsedTime - (NSTimeInterval(hours) * 3600)

That will compile, but it will crash at runtime if self.elapsedTime has no value.

It might be a compiler bug because -= should perhaps be equivalent to the last example, but instead produces a compiler error.

Darren
  • 25,520
  • 5
  • 61
  • 71