Xcode shows four errors.
First Error
let myCard = Card(rank: aRank!, suit: aSuit!)
^ Cannot invoke initializer for type 'Card' with an argument list of type '(rank: Card.Rank, suit: Card.Suit)'
We can't diagnose this without seeing the definition of the Card type.
Second Error
var deckOne = generateDeckOfCards()
^ Cannot use instance member 'generateDeckOfCards' within property initializer; property initializers run before 'self' is available
This error is telling you that you can't call generateDeckOfCards from this location because generateDeckOfCards is an instance method. The reason Swift doesn't let you call an instance method here is because, in general, the instance method might rely on the instance being fully initialized, and it's not fully initialized yet.
In this particular case, your generateDeckOfCards method doesn't use any instance methods or properties at all, so you can change it to be a static or class method instead:
static func makeDeckOfCards() -> [Card] {
var myDeckOfCards: Array = [Card]()
etc.
}
// Assuming this class is named DeckOfCards...
var deckOne = DeckOfCards.makeDeckOfCards()
If you fix the Second Error, Swift will give you an error on the next line:
var singleCard = deckOne[51]
^ Cannot use instance member 'deckOne' within property initializer; property initializers run before 'self' is available
This new error is very similar to the Second Error. You can't use one instance property in another property's initializer. Instead, you need to write an instance initializer:
var deckOne = DeckOfCards.makeDeckOfCards()
var singleCard: Card
init() {
// Property initializers run before init runs,
// so deckOne is already initialized.
singleCard = deckOne[51]
}
Third Error
var theCard = cardsInfo(singleCard)
^ Cannot use instance member 'cardsInfo' within property initializer; property initializers run before 'self' is available
This is the same error as the Second Error. You can't call the instance method cardsInfo here.
Since cardsInfo doesn't use any instance properties or methods, and uses several Card properties, you can replace cardsInfo with a computed property on the Card type. Delete your cardsInfo method and put this at global scope:
extension Card {
var cardInfo: (name: String, emoji: String, points: Int) {
return (name: rank.rankDescription(), emoji: suit.rawValue, points: rank.cardsValue())
}
}
Then you can try to declare theCard like this, and get a different error:
var theCard = singleCard.cardInfo
^ Cannot use instance member 'singleCard' within property initializer; property initializers run before 'self' is available
This is the same error you got after fixing the Second Error, and you fix this the same way. Initialize theCard in init:
var deckOne = DeckOfCards.makeDeckOfCards()
var singleCard: Card
var theCard: (name: String, emoji: String, points: Int)
init() {
// Property initializers run before init runs,
// so deckOne is already initialized.
singleCard = deckOne[51]
theCard = singleCard.cardInfo
}
Fourth Error
theCard.name
^ Expected declaration
You are directly inside a class or struct declaration here, so the only things allowed are declarations. theCard.name is not a declaration. Declarations usually start with let, var, or func.
I guess, since you are editing a playground, you wanted the playground to show the value of theCard.name here. That won't work for two reasons. First, playground execution stops at the first error. Second, you need to create a DeckOfCards instance and then you can ask it for its theCard.
class DeckOfCards {
static func makeDeckOfCards() {
blah blah blah
}
var deckOne = DeckOfCards.makeDeckOfCards()
var singleCard: Card
var theCard: (name: String, emoji: String, points: Int)
init() {
// Property initializers run before init runs,
// so deckOne is already initialized.
singleCard = deckOne[51]
theCard = singleCard.cardInfo
}
} // <-- This brace ends the declaration of DeckOfCards.
// AFTER ending the declaration of DeckOfCards, at the global scope:
let deck = DeckOfCards()
let card = deck.theCard
card.name
card.emoji
card.points