Swift - невозможно получить доступ к свойствам typealias после установки - PullRequest
1 голос
/ 22 января 2020

У меня есть загрузка объектов UIView, созданных с использованием класса SheetField.

Объекты обычно инициализируются во всем приложении следующим образом:

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

Мне нужно добавить дополнительное свойство 'letter' для этих объектов для доступа в одной части приложения, поэтому я создал typealias следующим образом:

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)

Затем я хочу назначить этим c буквам эти поля. Итак, у меня есть словарь букв:

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

И все oop для применения буквенных значений:

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

Поэтому я вызываю функцию следующим образом:

createLettersForFields(fields: [fieldX, fieldY, fieldZ]

Однако я не могу правильно назначить буквы. Я добавил пару операторов print в l oop:

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)") 
        }
    }
}

l oop, очевидно, каждый раз печатает штраф f.letter (f - поле, в которое мы передаем), но он выиграл вообще не печатать указанную c букву поля - значение всегда равно нулю. Я ожидал, что print ("(fieldX.letter)") будет печатать ноль до тех пор, пока l oop не достигнет поля fieldX, а затем напечатает присвоенное значение. Очевидно, что оператор print не важен, но он объясняет, почему я не могу получить доступ к fieldX.letter в других функциях, где он мне нужен.

Любая помощь будет принята с благодарностью.

ОБНОВЛЕНИЕ :

Я добавил условное выражение в l oop следующим образом:

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

И добавил точку останова в это условие. Я никогда не нажимаю на эту часть так ясно, что «f», которое я здесь использую, не равно полю, которое я инициализирую ... И все же, когда я печатаю «f» из функции и печатаю «fieldX» из инициализации, они кажутся одним и тем же объектом:

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:

Странно происходит! Я упростил для l oop и вынул перечисляемую часть:

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"
        }
    }
}

Здесь журнал печати возвращает ноль. Конечно, к тому времени, когда оно достигнет field.letter = "A", поле будет fieldX!

1 Ответ

0 голосов
/ 22 января 2020

Вы попали в ловушку типа значения .

В этой строке

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

f является копией fields, массив параметров и объекты fieldX, fieldY и fieldZ остаются неизменными. Вам не интересно, что вы не получите сообщение о том, что fields нельзя изменить, потому что это константа ?

Даже поля в массиве [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 не изменится.

...