0

I have the following class called User

class User: CustomStringConvertible {
    var id: Int!
    var firstName: String!
    var lastName: String!

    init(){
    }

    init(id: Int, firstName: String, lastName: String) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName
    }

    var description: String{
        return "id = \(id); first name = \(firstName); last name = \(lastName)"      
    }
}

I then call the class with the following code:

let user = User(id: userData["id"] as! Int, firstName: userData["first_name"] as! String, lastName: userData["last_name"] as! String)

After I call print(user) I get the following:

id = Optional(1); first name = Optional("John"); last name = Optional("Doe")

Why is it printing Optional(1), Optional("John"), when my variables are defined by Type!. I know the answer is probably very simple however I can't figure it out. It was working fine in Swift 2.0

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Bhavik P.
  • 905
  • 3
  • 10
  • 28
  • declare your class properties as constants and non optionals. `let id: Int let firstName: String let lastName: String` – Leo Dabus Mar 03 '17 at 02:28
  • `id`, `firstName`, `lastName` should **not** be optionals. What `User` has no first name or last name? – Alexander Mar 03 '17 at 02:37
  • I need init{} class there as well so I cannot simply delete the "!" else I will get an Return from initializer without initializing all stored properties error. – Bhavik P. Mar 03 '17 at 02:37
  • `class User: CustomStringConvertible { let id: Int let firstName: String let lastName: String init(id: Int, firstName: String, lastName: String) { self.id = id self.firstName = firstName self.lastName = lastName } var description: String{ return "id = \(id); first name = \(firstName); last name = \(lastName)" } }` – Leo Dabus Mar 03 '17 at 02:37
  • @BhavikP. Then that's a logical error in your program. Creating a user with out that information doesn't make any sense. – Alexander Mar 03 '17 at 02:58

2 Answers2

1

Change the init constructor to something like this

init(id: Int!, firstName: String!, lastName: String!) {
        self.id = id
        self.firstName = firstName
        self.lastName = lastName
    }

And the use guard-ifstatement to get a non-optional copy of the value

guard if let userID = userData["id"] as? Int, ..... else{
    return
}

Then initalize the User object with these values.

Pang Ho Ming
  • 1,299
  • 10
  • 29
1

In Swift 2, the type Int! was shorthand for ImplicitlyUnwrappedOptional<Int>. The compiler treated ImplicitlyUnwrappedOptional specially: it could be treated like Optional in contexts that allowed an Optional, and automatically (implicitly) unwrapped in contexts that didn't allow an Optional.

The problem was that it was hard to understand what the compiler would do with an Int! in various circumstances. Here's one of many examples:

func f() -> Int! { return 3 }
let x1 = f()

What is the type of x1 in that code, in Swift 2? Is it Int, ImplicitlyUnwrappedOptional<Int> (aka Int!), or Optional<Int> (aka Int?)? It turns out that in Swift 2, x1 is type Int?. You'd have to be a language guru to know that.

You can find more examples in this swift-evolution thread discussing the abolition of the ImplicitlyUnwrappedOptional type.

For Swift 3, the Swift team adopted SE-0054: Abolish ImplicitlyUnwrappedOptional type. SE-0054 removed the ImplicitlyUnwrappedOptional type entirely and changed the meaning of var id: Int!. Now it declares that id has type Optional<Int>, but if you use id where only a plain Int is accepted, then the compiler implicitly unwraps it for you. In all other contexts, id is treated as a Int? (aka Optional<Int>). Whenever the compiler can treat id as Int?, it will do so.

This is why your results are different between Swift 2 and Swift 3. In Swift 2, the compiler would implicitly unwrap id (and the other properties) in more places than it will in Swift 3. Since string interpolation ("\(...)") can accept any type, the Swift 3 compiler passes id as Int? instead of implicitly unwrapping it.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848