UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

unwrapping optional array

Forums > Swift

I have declared a Card class, which includes:

var cards: [Card?] = [] var otherCards: [Card?] = [] cards.reserveCapacity[3] otherCards.reserveCapacity[3]

Later, in another class and function, I have declared:

var visibleCards = [Card]() visibleCards.reserveCapacity(6)

and am then trying to do:

visibleCards = currentPlayer.cards

and get an error: Cannot assign value of type '[Card?]' to type '[Card]' with the follow-on:

  1. Arguments to generic parameter 'Element' ('Card?' and 'Card') are expected to be equal

and then:

visibleCards.append(otherCards)

and get an error: Value of optional type 'IdiotCard?' must be unwrapped to a value of type 'IdiotCard'

So, can you unwrap the optional arrays in one call (and if so, how?), or do I need to unwrap each element separately (and, if you don't mind, how)? Sorry, the confusion of a newbie...

The cards and otherCards arrays can have nil elements (which need to be preserved in the arrays), as those arrays record the position on the board of cards laid out next to each other, and there could be 1, 2, or all 3 missing cards.

I have not declared the visibleCards array as optional, as I need to sort it. Thx, Bill

2      

Is there any reason why use [Card?]? Why not empty array or even [Card]?? In your case you can use compactMap on the array of optionals to unwrap them

2      

  • Well, I don't understand the difference between [Card?] and [Card]?, so I can't address that issue. Can you please explain the difference?
  • I need the arrays to be optional because they may contain nil elements.
  • How would using an empty array help me? When you say "empty array", are you meaning that I don't reserve capacity for the array? If so, why is that a good idea? If you mean something else, what do you mean?

2      

Well, I don't understand the difference between [Card?] and [Card]?, so I can't address that issue. Can you please explain the difference?

[Card?] is an array that can contain items that are either a Card object or nil.

[Card]? is either an array of Card objects or nil. The individual objects inside the array cannot be nil.

2      

You suggested that I could use compactMap to unwrap the arrays, but as I read it, compactMap deletes the nil elements, which I said was not okay. Apparently, compactMap will not work (unless I am misunderstanding the hackingwithswift article on map, flatMap, and compactMap.

2      

Well compactMap will return a new array without the nil elements so the original array will stay intact.

I am guessing you are also working with nil values somehow and that is why you are using [Card?]. So you either need to have the another array be this same type - meaning array of optional Card? elements or change your approach. For example you could define another property on Card that would tell you that this card is "nil" and so needs to be handled differently.

2      

How do you use compactMap to delete the nil elements from the array, and make no change to the non-nil class instances in the array?

I have tried compactMap{}, compactMap{Card}, compactMap{$0}, compactMap{$0 = various things...}, compactMap{ _ in Card}. In each case, I get some mis-match between the unwrapped item and my Card class. Usually, this is a mismatch between the first element of my class definition (so, maybe String or Int or SKSpriteNode--I have changed the class definition by moving properties of the class, to no avail) and Card?, or a mismatch between Card and Card?. My other thought is that perhaps I need to write a separate function that is the closure and then call that function, instead of trying to write the closure inline with the compactMap call. Sorry, I am really out of ideas at this point. @nemecek-filip, thanks for your idea about defining another property on the class; I have not forgotten that and will try it out if I cannot figure out how to use compactMap on an array of class instances. All the examples and explanations of compactMap I can find just use String or Int, and I think I do understand those, but the leap to an array of class instances that I want the closure to make no modifications to has me stymied.

I guess I still also have the basic question, can I unwrap the array in a single call to compactMap (and, if so, what would the closure need to look like to make no change to the non-nil array elements?), or do I need to unwrap each array element separately? Or, an I just missing something really fundamental?

2      

You do it like this:

let cards: [Card?] = //...get your array of Optional Cards somehow
let nonNilCards = cards.compactMap { $0 } //this will be of type [Card]

2      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.