Swift - 设置后无法访问类型别名属性

Swift - unable to access typealias properties once set

我有一大堆 UIView 对象是使用名为 'SheetField' 的 class 创建的。

对象通常在整个应用程序中初始化如下:

objectx = SheetField(title: "example", value: "example")

我需要向这些对象添加额外的 属性 'letter' 以在应用程序的一部分中访问,因此我创建了一个类型别名,如下所示:

typealias NewSheetField = (field: SheetField, letter: String?)

因此,我声明这些字段对象如下:

private var fieldX: NewSheetField
private var fieldY: NewSheetField   
private var fieldZ: NewSheetField

我这样初始化它们:

fieldX = NewSheetField(field: SheetField(title: "example", value: "example"), letter: nil)
fieldY = NewSheetField(field: SheetField(title: "example", value: "example"), letter: nil)
fieldZ = NewSheetField(field: SheetField(title: "example", value: "example"), letter: nil)

然后我想为这些字段分配特定的字母。所以,我有一个字母字典:

private let letters = [0: "A", 1: "B", 2: "C", 3: "D", 4: "E", 5: "F", 6: "G", 7: "H"]

以及应用字母值的循环:

func createLettersForFields(fields: [NewSheetField]) {
    for (index, var f) in fields.enumerated() {
        if let letterToAdd = letters[index] {
            f.letter = letterToAdd
        }
    }
}

所以我这样调用函数:

createLettersForFields(fields: [fieldX, fieldY, fieldZ]

但是,我似乎无法正确分配字母。我在循环中添加了几个打印语句:

func createLettersForFields(fields: [NewSheetField]) {
    for (index, var f) in fields.enumerated() {
        if let letterToAdd = letters[index] {
            f.letter = letterToAdd
            print("\(f.letter)")
            print("\(fieldX.letter)") 
        }
    }
}

循环显然每次都打印出 f.letter 正常(f 是我们传入的字段)但它根本不会打印出特定的字段字母 - 值始终为零。我所期望的是 print("(fieldX.letter)") 将打印 nil 直到循环命中 fieldX 字段然后打印分配的值。显然 print 语句并不重要,但它解释了为什么我无法在需要它的其他函数中访问 fieldX.letter。

如有任何帮助,我们将不胜感激。

更新:

我在循环中添加了条件语句如下:

if f == fieldX {
print("TEST")
}

并在此条件下添加了一个断点。我从来没有这么清楚地击中这部分,我在这里使用的 'f' 不等于我正在初始化的字段......然而当我从函数打印 'f' 并打印 'fieldX' 从 init 开始,它们似乎是同一个对象:

PRINTED FROM METHOD: (field: <SheetField: 0x125e56240; frame = (0 0; 0 0); layer = <CALayer: 0x2824c70a0>>, letter: Optional("A"))

PRINTED FROM INIT : (field: <SheetField: 0x125e56240; frame = (0 0; 0 0); layer = <CALayer: 0x2824c70a0>>, letter: nil)

更新 2:

奇怪的事情发生了!我简化了for循环,把枚举的部分去掉:

func createLettersForFields(fields: [NewSheetField]) {
    for var field in fields {
        if field == fieldX {
            fieldX.letter = "A"
        }
    }
}

这有效并将 'A' 分配给 fieldX。当我登录 fieldX.letter 时,我得到 "A"。但是,当我将 'fieldX' 换成 'field' 时,它仍然不会分配:

func createLettersForFields(fields: [NewSheetField]) {
    for var field in fields {
        if field == fieldX {
            field.letter = "A"
        }
    }
}

这里,打印日志returns nil。 当然,当它到达 field.letter = "A" 时,字段是 fieldX !

您陷入了 值类型陷阱

在这一行

for (index, var f) in fields.enumerated() {

ffields的副本,参数数组和对象fieldXfieldYfieldZ保持不变。你不奇怪你没有得到关于 fields cannot be modified because it's a constant?

的错误

连数组[fieldX, fieldY, fieldZ]中的字段都是三个字段的副本

如果保留对原始对象的引用至关重要,请使用 类 引用类型。

否则您必须将数组创建为变量,将其作为 inout 传递并直接修改数组中的项目。请注意,枚举中的 element 未使用,因为您必须将 letterToAdd 直接分配给数组中的项目

由于 letter 是可选的,可选的绑定是多余的

private var fieldX = NewSheetField(field: SheetField(title: "example", value: "example"), letter: nil)
private var fieldY = NewSheetField(field: SheetField(title: "example", value: "example"), letter: nil)
private var fieldZ = NewSheetField(field: SheetField(title: "example", value: "example"), letter: nil)

private let letters = [0: "A", 1: "B", 2: "C", 3: "D", 4: "E", 5: "F", 6: "G", 7: "H"]

func createLettersForFields(fields: inout [NewSheetField]) {
    for (index, _) in fields.enumerated() {
        fields[index].letter = letters[index]
    }
}

var theFields = [fieldX, fieldY, fieldZ]
createLettersForFields(fields: &theFields)
print(theFields)

请注意,即使采用这种方式,private var fieldX/Y/Z 的内容也不会改变。