Joey
Joey

Reputation: 621

How to declare [Int] in optional

How to declare [Int] in optional

I try

var listofNumber = [Int]?()

But it's not working

But if I try

var listofNumber : [Int]?

The problem is I cant use listofNumber.append anymore

Value of type '[Int]?' has no member 'append'

Upvotes: 0

Views: 804

Answers (3)

CodingMeSwiftly
CodingMeSwiftly

Reputation: 3261

You are writing [Int]? but this is just syntactic sugar.

Behind the scenes, what you're actually declaring isOptional<[Int]>.

If you look at the documentation for Optional<T>, you can see that there are three initialisers declared for this value type:

  • init(from: Decoder) throws This one is used in conjunction with the coding protocols introduced in Swift 4. It is of no relevance here.
  • init(nilLiteral: ()) This one initialises the Optional<T> to nil.
  • init(some: T) This one initialises the Optional<T> to T.

Your statement var listOfNumbers = [Int]?() does not match any of the initialisers and thus is not working.

Now what you probably want to do - and what most of us would presumably do here - is:

var listOfNumbers: [Int]? = []

This declares the type of listOfNumbers to be [Int]? (aka Optional<[Int]>) and at the same time sets its initial value to an empty array.

The crucial thing to note here is that virtually all of this is syntactic sugar. If you went out of your way and defined the var "natively", it would look something like this:

var listOfNumbers = Optional<[Int]>(Array<Int>()).

(You could leave out the generic parameter to Array, as it would be inferred by the type system here.)

Since this is cumbersome to write and also doesn't read quite well, you can use the short version.

As for the second issue regarding Array.append. Your var is of type [Int]? (aka Optional<[Int]>) and thus you cannot access vars or call methods defined on the Array type. You need to unwrap the optional first.

listOfNumbers?.append(4711).

If you're using Xcode, it should actually provide you with a fix-it for this kind of issue.

Now since we were talking about "explicitness" anyway:

listOfNumbers?.append(4711) is again a shiny example for syntactic sugar.

Explicitly written, it would look something like this:

// Optional<T> is actually an enum, so we can switch over it.
switch listOfNumbers {
case .some(var value):
  value.append(4711)
case .none:
  break
}

// Alternative
if case .some(var value) = listOfNumbers {
  value.append(4711)
}

As you can see, this is quickly getting bloated, especially considering optional chaining, etc. Hence, the short version was "invented".

I've written this long answer to make it clear to you what's going on behind the scenes here and I guess it never hurts to remind yourself of the nuts and bolts you’re building upon sometimes.


Update

Note that it would be perfectly valid for you to write the statement like this:

var listOfNumbers = [Int]?([])
or
var listOfNumbers = [Int]?(nilLiteral: ())

The amount of syntactic sugar you are using it up to you and you can mix it with "explicit" coding however you want.

Upvotes: 5

Andy Jazz
Andy Jazz

Reputation: 58103

For declaring use this syntax:

var listOfNumber: [Int]? = []

Then use any method you need:

listOfNumber?.append(20)
listOfNumber?.insert(40, atIndex: 1)

listOfNumber!                               // result: [20,40]

Second part.

Here's your code:

if listOfNumber?[0] == nil {
    print("if access...")
} else { 
    listOfNumber?.append(20)
    print(listOfNumber!)
}

Upvotes: 2

CZ54
CZ54

Reputation: 5588

var listofNumber : [Int]? is the good approch.

Dont forget to init using

var listofNumber : [Int]? = [] or var listofNumber : [Int]? = nil

After, as the array is optional, use listofNumber?.append(10).

Upvotes: 1

Related Questions