0

I have the following code:

struct Product {
    var image: URL!
    var title: String!
    var price: Price!
    var rating: Float!
    var url: URL!
}

struct Price {
    var value: Double!
    var currency: String!  // should be enum
}

I later initialize a Product with:

product = Product(
    image: URL(string: "...")!,
    title: "...",
    price: Price(
        value: 5.99,
        currency: "CAD"
    ),
    rating: 4.5,
    url: URL(string: "...")!
)

During runtime, product.price is of type Price? I find this weird since it's implicitly unwrapped.

I've tried giving Price an init() method, with the same results. I've also tried using var price: Price! = Price(value: 0, currency: "CAD") in the Product definition, with the same results. (I add a memberwise initializer to Price.)

What's going on here?

Daniel Que
  • 1,734
  • 4
  • 20
  • 31
  • 1
    Why are the struct properties implicitly unwrapped optionals in the first place? This is not clear. Since you're unwrapping the values anyway, you should just use non-optional properties and use the memberwise initializer. – Eric Aya Dec 12 '16 at 14:42
  • How did you check that *"`product.price` is of type `Price?`"* – Note that ImplicitlyUnwrappedOptional is no longer a distinct type in Swift 3. See e.g. http://stackoverflow.com/questions/39537177/swift-3-incorrect-string-interpolation-with-implicitly-unwrapped-optionals or http://stackoverflow.com/questions/39633481/implicitly-unwrapped-optional-assign-in-xcode-8. – Martin R Dec 12 '16 at 14:49
  • I'm using non-optional properties, and it fixes the issues I was experiencing. It's still weird that it's not throwing any errors though, right? I checked using the debugger. (`print product.price`) – Daniel Que Dec 12 '16 at 14:56
  • For every unjustified implicitly unwrapped optional, force cast or forced coercion, an adorable little kitten cries, somewhere in the world. – Alexander Dec 12 '16 at 14:56
  • @DanielQue It's an implicitly unwrapped optional, which is an optional. – Alexander Dec 12 '16 at 14:56
  • Thanks, sorry for the confusion. – Daniel Que Dec 12 '16 at 14:57

2 Answers2

5

During runtime, product.price is of type Price? I find this weird since it's explicitly set to be non-optional

No, you explicitly set it to be optional:

struct Product {
  var image: URL! // <-- Explicitly marked as optional via '!'
}

if you want it to be non-optional, do not mark it as optional via ! or ?:

struct Product {
  var image: URL // <-- not marked as optional
}

Both ! and ? are optionals. The only difference being that the latter needs to be explicitly unwrapped (if let) while the former is automatically unwrapped (potentially leading to crashes if used incorrectly).

hnh
  • 13,957
  • 6
  • 30
  • 40
1

Perhaps because in Swift 3 implicitly unwrapped optionals are backed by ordinary Optionals.

Proposal for abolishing IUO:

However, the appearance of ! at the end of a property or variable declaration's type no longer indicates that the declaration has IUO type; rather, it indicates that (1) the declaration has optional type, and (2) the declaration has an attribute indicating that its value may be implicitly forced. (No human would ever write or observe this attribute, but we will refer to it as @_autounwrapped.) Such a declaration is referred to henceforth as an IUO declaration.

Andreas
  • 2,665
  • 2
  • 29
  • 38