Is it possible to have a nil value in a tuple with

2019-08-08 21:03发布

I'm trying to write some code for seeding some test data into the Core Data database in an application I'm developing, about Pokémon. My code for seeding is based on this: http://www.andrewcbancroft.com/2015/02/25/using-swift-to-seed-a-core-data-database/

I am having a slight problem with one thing though. I don't seem to be able to put a nil value inside of a tuple.

I'm currently trying to seed some Pokémon Moves into the database. A move can have a bunch of different properties, but which combination it has it entirely dependent on the move itself. All seed Move data is in an array of tuples.

To demonstrate...

let moves = [
    (name: "Absorb", moveType: grass!, category: "Special", power: 20, accuracy: 100, powerpoints: 25, effect: "User recovers half the HP inflicted on opponent", speedPriority: 0),
    // Snip
]

...is fine. It's a move with all the above properties, where zero in speedPriority means something. However, some moves don't have a power or accuracy property, because they're irrelevant to that specific move. However, creating a second tuple in the array without the power or accuracy named elements, such as...

(name: "Acupressure", moveType: normal!, category: "Status", powerpoints: 30, effect: "Sharply raises a random stat", speedPriority: 0)

...understandably throws an error

Tuple types {firstTuple} and {secondTuple} have a different number of elements (8 vs. 6)

because, well, the tuples have different number of elements. So instead, I tried...

(name: "Acupressure", moveType: normal!, category: "Status", power: nil, accuracy: nil, powerpoints: 30, effect: "Sharply raises a random stat", speedPriority: 0)

but this also didn't work, as it gave the error:

Type 'Int' does not conform to protocol 'NilLiteralConvertible'

So, is there any way to do what I'm trying to do? Is there some way to either place a nil value inside the tuple, or somehow make it an optional element? With thanks!

3条回答
Explosion°爆炸
2楼-- · 2019-08-08 21:22

You could do something like below:

typealias PokemonMove = (name: String?, category: String?)

var move1 : PokemonMove = (name: nil, category: "Special")

let moves: [PokemonMove] = [
    (name: nil, category: "Special"),
    (name: "Absorb", category: "Special")
]

Add more parameters as you wish, I took just two parameters for explanation of concept.

查看更多
冷血范
3楼-- · 2019-08-08 21:34

In the tutorial the tuples only contained two values - name and location. Since you have so many variables in one tuple you should conside putting them into a class or struct.

Using Structs or Classes also makes it easy for variables to be nil. And, since optional types have a default value of nil when setting up each move you only need to set the values that aren't nil - as shown the second example.

An example Struct is:

struct Move {
    var name: String?
    var moveType: String?
    var category: String?
    var power: Int?

    // etc etc...
}

You could then create a move:

var move = Move()
move.name = "Acupressure"
move.category = "Status"
// Don't need to set move.power to nil - it is already!

In the tutorial you need to enumerate your array of Tuples, for this to work with Structs it basically looks the same:

let moves: [Move] = // My array of moves
for move in moves {
    let newMove = NSEntityDescription.insertNewObjectForEntityForName("Move", inManagedObjectContext: context) as CoreDataMove
    newMove.name = move.name
    newMove.moveType = move.moveType
    newMove.category = move.category

    // etc etc
}
查看更多
The star\"
4楼-- · 2019-08-08 21:38

You can achieve that using:

import Foundation

let myNil : Any? = nil

let moves = [
    (name: 1 as NSNumber, other: ""),
    (name: myNil, other: "" )
]

moves[0].name // 1
moves[1].name // nil
查看更多
登录 后发表回答