2015-12-11 61 views
1

我有一小段代码,看起来像这样:多维数组不让我通过循环赋值?

func initAllLabels() { 

    var scoreLabels:[[[SKLabelNode]]] = [] 

    for (var x = 0; x < modesInGame; x++) { 
     for (var y = 0; y < levelsInMode; y++) { 
      for (z = 0; z < labelsInLevel; z++) { 
       scoreLabels[x][y][z] = SKLabelNode(fontNamed: "Font") 
      } 
     } 
    } 
} 

所以我试图做的是我的所有标签存储每个游戏模式。我试图用一个多维数组的原因是因为我将有每级(3-5)几个标签,我想访问他们像这样:

updateText(scoreLabels[currentMode][currentLevel][thisLabel]) 

和访问所有标签当前标签是这样的:

for label in labelsInLevel: 
    label.hidden = false 

的问题是,当我尝试在initAllLabels比赛开始创建我的所有标签,我在循环中第一次运行得到一个“索引超出范围”的错误(索引:0)。我认为这个问题是因为我需要在设置其内容之前“追加”到数组中,对吗?我会如何在像我这样的数组结构中完成这项工作?

+0

可能重复的[如何创建Swift空的二维数组与大小](http://stackoverflow.com/questions/24811456/how-to-create-swift-empty-two-dimensional-array-with -size) –

回答

2

您需要将数组初始化为给定大小,然后更新其中位置的项目。它可能有助于从一维情况开始:

var labels: [SKLabelNode] = [] // creates an empty array 
// since the array is empty, this will generate an index out of range error: 
labels[0] = SKLabelNode(fontNamed: "Font") 

相反,您需要使用要添加的元素来扩展数组。例如,

for _ in 0..<labelsInLevel { 
    labels.append(SKLabelNode(fontNamed: "Font")) 
} 

(在_的意思是“我不关心每个迭代的实际数量 - 通常,如果你想知道这是围绕环路i个时间,你会写for i in 0..<n

虽然有更好的方法来做到这一点。但小心与他们中的一个,Array初始化,需要一个countrepeatedValue

let labels = Array(count: labelsInLevel, repeatedValue: SKLabelNode(fontNamed: "Font”)) 

SKLabelNode是引用类型。这意味着一个变量仅指一个实例,并且将一个变量分配给另一个变量只会复制参考。例如:

let variableOne = SKLabelNode(fontNamed: "Foo") 
let variableTwo = variableOne 
// variableTwo now refers to the same instance of SKLabelNode 
variableTwo.fontName = "Bar" 
print(variableOne) 
// fontName will now be “Bar” even though this was 
// done via variableTwo 

您可以获得与上面repeatedValue代码相同的效果。该标签只创建一次,并且多次插入相同的引用。更改数组中一个标签上的属性,然后将其全部更改。请注意0​​循环版本不是有这个问题。每次循环时,都会创建一个新的SKLabelNode实例。他们不会被分享。

的替代repeatedValue初始化,即不使用for循环创建是使用map

(0..<labelsInLevel).map { _ in SKLabelNode(fontNamed: "Font") } 

这里,就像在for环版本,一个新的SKLabelNode实例被创建每次。

(同样,我们使用_,表示我们并不关心迭代次数)

最后,创建内部循环嵌套的多维数组,你可以运行map多次:

var scoreLabels = 
    (0..<modesInGame).map { _ in 
    (0..<levelsInMode).map { _ in 
     (0..<labelsInLevel).map { _ in 
     SKLabelNode(fontNamed: "Font") 
     } 
    } 
    } 
+0

真的很欣赏详细的回应,这个解决方案完全没有问题! – user1547019

-2

你需要的,如果你希望所有SKLabelNode在不同SKLabelNodes指向初始化3D阵列像这样:

func initAllLabels() { 

    var scoreLabels = [[[SKLabelNode]]](count: modesInGame, repeatedValue: 
     [[SKLabelNode]](count: levelsInMode, repeatedValue: 
     (0..< labelsInLevel).map { _ in SKLabelNode(fontNamed: "Font") })) 
} 

的repeatedValue是您存储在电池(类型或值)和计数有什么表现您想要将其存储在阵列中的次数。

PS:这个答案已经用Xcode Playground测试过,并且工作得很好。


我按照Airspeed Velocity的评论编辑了我的答案。

+1

请注意,这将创建一个内部数组,每个元素引用_same_标签实例,因为'SKLabelNode'是一种参考类型。改变它会改变它在每个条目。要创建一个不同标签的数组,使用'map':'var scoreLabels = Array(count:modesInGame,repeatedValue:Array(count:levelsInMode,repeatedValue:(0 ..