【问题标题】:Swift 2D Array Initialisation with Objects使用对象进行 Swift 2D 数组初始化
【发布时间】:2016-02-15 13:58:38
【问题描述】:

我正在尝试用每个单元格中的对象初始化一个二维数组。 我从一门课开始,

class cell {
    var up = 1
    var down = 1
    var right = 1
    var left = 1
}

然后像这样初始化我的数组:

let row = Array<cell!>(count: 10, repeatedValue: cell())
let myArray = Array(count: 10, repeatedValue: row)

现在效果很好...直到我更改其中一个对象的属性。

myArray[0][0].left = 0

那么 Array 中的所有对象都将其“left”属性设置为 0。

如何在 Array 中创建相互独立的对象? (不使用 for 循环单独附加每个项目)

【问题讨论】:

  • 如何将对象添加到数组中?您是否每次都在将其添加到数组之前创建新的单元格实例?
  • 在本例中,将cell 设为struct 而不是class

标签: ios arrays swift swift2


【解决方案1】:

这不适用于Cell 作为class,因为这是一个引用类型,所以数组中的每个单元格都将是对同一个单元格的引用。如果可以,请将Cell 更改为struct 而不是class。作为值类型,每个单元格都是唯一的副本。

如果Cell 必须是class,您可以使用嵌套的maps 创建myArray(技术上仍然是循环):

let myArray:[[Cell!]] = (1...10).map { _ in (1...10).map { _ in Cell() } }

注意,classstruct 名称应使用以大写字母开头的名称,这就是我将您的 cell 更改为 Cell 的原因。

【讨论】:

  • 非常“迅速”的答案! (已投票。)我需要更好地思考函数式编程术语。
  • 很好地使用map
【解决方案2】:

这是因为Cell 是一个类,而类是引用类型。因此,第一行创建了一行,其中包含对同一单元格的 10 个引用。第二行创建 10 个唯一行(数组是 structs,因此是值类型),但所有唯一行都有 10 个对同一单元格的引用。

有几种方法可以解决这个问题。您可以确保创建 100 个独特的单元格:

var array = [[Cell]]()
for _ in 0 ..< 10
{
    var row = [Cell]()
    for _ in 0 ..< 10
    {
        row.append(Cell())
    }
    array.append(row)
}

或者,您可以考虑将Cell 设为结构,如果Cell 与您的示例一样简单并且您不需要继承,这可能是最好的主意。

struct Cell
{
    var up = 1
    var down = 1
    var right = 1
    var left = 1
}

在这种情况下,您可以按照您期望的方式初始化数组。

var array = [[Cell]](count: 10, repeatedValue: [Cell](count: 10, repeatedValue: Cell())) 

【讨论】:

  • Jeremy 的回答比我的好,因为他展开了内部和外部初始化并完全解决了问题,而我只是暗示了内部对象的问题。
【解决方案3】:

你的类cell 工作是一个引用类型。这意味着什么 ? 嗯,Apple's explanation的话题就够了:

Swift 中的类型属于以下两类之一:第一,“值类型”, 每个实例保留其数据的唯一副本,通常定义 作为结构、枚举或元组。第二个,“引用类型”,其中 实例共享数据的单个副本,类型通常为 定义为一个类。在这篇文章中,我们探讨了价值的优点和 引用类型,以及如何在它们之间进行选择。

通过将cell 声明为class,这是一个引用类型。

引用类型

// let's create an object
let cell1 = Cell()
// now we add a reference to this object
let cell2 = cell1

// now we change the top of cell1
cell1.up = 10

NSLog("\(cell2.up)")  
// -> outputs : 10
// Since cell1 and cell2 represents the same object, 
// you can't modify cell1 without modifying ce22.

如果您将cell 声明为struct 而不是class,会发生什么情况?它变成了一个值类型:

值类型

// let's create an object
let cell1 = Cell()

// now we create a new object, cell2, with the value initialized 
// with cell1's value. It's a copie, not a reference
let cell2 = cell1

// now we change the top of cell1
cell1.up = 10

NSLog("\(cell2.up)")  
// -> outputs : 0
// Here cell1 and cell2 are totally different objects

【讨论】:

    【解决方案4】:

    你正在做的事情不会奏效。如果您尝试创建一个数组并填充它重复值并且重复值是一个对象,则该数组包含对同一对象的多个引用。 (对象是一种“引用类型”。添加到容器时,添加的是对对象的引用,而不是副本。)

    您需要为外部数组中的每个条目创建一个新对象:

    (编辑以创建字符串对象数组,因为我无权访问 OP 的 cell 类)

    typealias rowArray = [String!]
    var myArray = [rowArray]()
    for i in 1...10
    {
      myArray.append(rowArray(count: 10, repeatedValue: "Foo"))
    }
    

    请注意,您的内部数组将面临同样的问题。您没有唯一的单元格对象数组 - 您有一个包含对单个单元格对象的多个引用的数组。

    【讨论】:

    • 您的示例具有误导性,因为Int! 是值类型,而不是引用类型。
    • 是的。我变得懒惰了。我想在操场上对代码进行语法检查,并且没有 OP 对“单元”的定义,所以我将其改为 Int,但这改变了问题的性质。感谢您指出这一点。
    • 很抱歉一直缠着你,但String! 也是一个值类型。
    • 是吗?我以为 String 是对象/引用类型?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-29
    • 1970-01-01
    • 2013-02-04
    • 1970-01-01
    • 2018-06-22
    • 1970-01-01
    • 2017-02-16
    相关资源
    最近更新 更多