Swift 的元组中是否可以有 nil 值?

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

我正在尝试编写一些代码,以便在我正在开发的应用程序中将一些测试数据播种到核心数据数据库中,关于 Pokémon。我的播种代码基于此:http://www.andrewcbancroft.com/2015/02/25/using-swift-to-seed-a-core-data-database/

不过有一件事我有点小问题。我似乎无法将 nil 值放入元组中。

我目前正在尝试将一些 Pokémon Move 播种到数据库中。一个动作可以有一堆不同的属性,但它具有哪种组合完全取决于动作本身。所有种子 Move 数据都在一个元组数组中。

演示...

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
]

...很好。这是一个具有上述所有属性的移动,其中 speedPriority 中的零意味着什么。但是,有些动作没有 poweraccuracy 属性,因为它们与特定动作无关。但是,在没有 poweraccuracy 命名元素的数组中创建第二个元组,例如...

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

...可以理解地抛出一个错误

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

因为,嗯,元组有不同数量的元素。所以相反,我尝试了...

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

但这也没有用,因为它给出了错误:

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

那么,有什么方法可以做我想做的事情吗?有没有办法在元组中放置一个 nil 值,或者以某种方式使其成为可选元素?谢谢!

您可以执行如下操作:

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

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

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

想加多少就加多少,我只拿了两个参数来解释概念。

您可以使用:

import Foundation

let myNil : Any? = nil

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

moves[0].name // 1
moves[1].name // nil

在教程中,元组仅包含两个值 - namelocation。 由于一个元组中有这么多变量,您应该考虑将它们放入 class 或结构中。

使用 Structs 或 类 也使得变量很容易为 nil。而且,由于可选类型在设置每个移动时具有默认值 nil,因此您只需要设置不为零的值 - 如第二个示例所示。

一个示例结构是:

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

    // etc etc...
}

然后您可以创建一个移动:

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

在本教程中,您需要枚举元组数组,为了与 Structs 一起使用,它基本上看起来是一样的:

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
}