Могу ли я объявить локальную переменную Array по ссылке, чтобы уменьшить дублирование кода - PullRequest
0 голосов
/ 04 июля 2018

Итак, я знаю, что Swift Arrays имеют значение struct, поэтому они передаются по значению

Вот мой код:

firstSnapshotList и secondSnapshotList оба [Snapshot]

    if datePicker == firstDatePicker {
        firstSnapshotList.removeAll()

        if let snapshots = SnapshotList.snapshotDict[dateKey] {
            for snapshot in snapshots {
                firstSnapshotList.append(snapshot)
            }
        }
    } else if datePicker == secondDatePicker {
        secondSnapshotList.removeAll()

        if let snapshots = SnapshotList.snapshotDict[dateKey] {
            for snapshot in snapshots {
                secondSnapshotList.append(snapshot)
            }
        }
    }

так что, как видите, оба блока, если операторы if одинаковы, за исключением изменяемого массива.

Я хотел бы сначала объявить переменную, var snapshotList = *snapshot reference*, и затем, если бы я мог установить эту ссылку либо на firstSnapshotList, либо на secondSnapshotList в зависимости от выбора даты, тогда мой код был бы просто

if datePicker == firstDatePicker {
    snapshotList = firstSnapshotList
} else if datePicker == secondDatePicker {
    snapshotList = secondSnapshotList
}

snapshotList.removeAll()

if let snapshots = SnapshotList.snapshotDict[dateKey] {
    for snapshot in snapshots {
        snapshotList.append(snapshot)
    }
}

Вы могли бы утверждать, что количество строк одинаково, так что это на самом деле не является более читабельным или обслуживаемым - это просто личное предпочтение для меня, я думаю, что вторая версия имеет больше смысла, в основном потому, что нет повторения код

Но если это только часть образа жизни Свифта, я тоже могу с этим жить. Просто интересно, можно ли вообще объявить переменную как ссылку

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Ваш код может быть упрощен до такой степени, что нет необходимости уменьшать дублирование кода:

let newSnapshotList = SnapshotList.snapshotDict[dateKey] ?? []

if datePicker == firstDatePicker {
    firstSnapshotList = newSnapshotList
} else if datePicker == secondDatePicker {
    secondSnapshotList = newSnapshotList
}

Но для ответа на вопрос это можно сделать, объявив вложенную функцию в существующей функции:

func overrideFromSnapshotDict(destination: inout [YourType]) {
    destination.removeAll()
    if let snapshots = SnapshotList.snapshotDict[dateKey] {
        for snapshot in snapshots {
            destination.append(snapshot)
        }
    }
}

if datePicker == firstDatePicker {
    overrideFromSnapshotDict(destination: &firstSnapshotList)
} else if datePicker == secondDatePicker {
    overrideFromSnapshotDict(destination: &secondSnapshotList)
}
0 голосов
/ 04 июля 2018

Как вы сказали, массивы Swift являются структурами, и они действительно передаются как значения. Вместо этого вы можете передать массив отдельному методу в качестве аргумента inout:

func yourMethodName(_ array: inout [Snapshot]) {
    array.removeAll()

    if let snapshots = SnapshotList.snapshotDict[dateKey] {
        for snapshot in snapshots {
            array.append(snapshot)
        }
    }
}

Тогда просто вызовите метод там, где он вам нужен, вот так:

if datePicker == firstDatePicker {
    yourMethodName(&firstSnapshotList)
} else if datePicker == secondDatePicker {
    yourMethodName(&secondSnapshotList)
}
0 голосов
/ 04 июля 2018

Массивы, как и все коллекции переменного размера в стандартной библиотеке, используют оптимизацию копирования при записи. Несколько копий массива находятся в одном и том же хранилище, пока вы не измените одну из копий. Когда это происходит, изменяемый массив заменяет свое хранилище своей уникальной копией, которая затем модифицируется на месте. Иногда применяются оптимизации, которые могут уменьшить объем копирования.

...