Как изменить порядок свойств структур Swift?

У меня есть структура, в моем случае это User.

Пример структуры со свойствами (например, у нее всего несколько свойств).

struct User {
   var name:String?
   var email:String?
}

Теперь я создаю структуру User с определенным порядком (адрес электронной почты, имя) полей.

var user = User()
user.email = "[email protected]"
user.name = "Oleg"

И теперь я делаю dump структуры, чтобы увидеть порядок свойств.

dump(user)

▿ __lldb_expr_21.User
  ▿ name: Optional("Oleg")
    - some: "Oleg"
  ▿ email: Optional("[email protected]")
    - some: "[email protected]"

Итак, можно ли изменить порядок свойств структур, чтобы они были в том же порядке, в котором я их добавил? Или мне следует использовать Array для сохранения порядка свойств?

Ожидаемый результат dump:

▿ __lldb_expr_25.User
  ▿ email: Optional("[email protected]")
    - some: "[email protected]"
  ▿ name: Optional("Oleg")
    - some: "Oleg"

person Oleg Gordiichuk    schedule 19.06.2017    source источник
comment
User имеет два свойства, и не имеет значения, в каком порядке вы присваиваете им значения. Почему? – Также dump() предназначен для отладки, и вам не следует полагаться на определенный порядок, в котором он печатает свойства.   -  person Martin R    schedule 19.06.2017
comment
Пользовательская структура @MartinR имеет более 20 свойств в реальном проекте. У меня есть проблема с устаревшим проектом, когда требуется иметь возможность регистрировать последовательность свойств структуры так, как я описываю.   -  person Oleg Gordiichuk    schedule 19.06.2017
comment
Почему порядок важен? Порядок будет порядком, определенным в определении структуры. Если по какой-то причине вам нужно поддерживать порядок, в котором свойства были установлены для каждого экземпляра структуры, вы можете добавить подходящий массив и некоторые наблюдатели свойств, чтобы сохранить порядок.   -  person Steve Ives    schedule 19.06.2017
comment
@OlegGordiichuk Действительно ли имеет смысл иметь пользователя без имени или электронной почты?   -  person Alexander    schedule 19.06.2017


Ответы (3)


Алгоритм размещения структур в памяти еще точно не определен. Это отслеживается в SR-3723. Это вполне может измениться в будущем по целому ряду причин:

  • члены могут быть более плотно упакованы, если компилятор не ограничен сохранением порядка, что приводит к меньшему расходу памяти на заполнение для соблюдения ограничений выравнивания.
  • члены могут быть плотно упакованы для лучшей локализации (таким образом, лучшей производительности кэша) для часто используемых операций.

Дело в том, что вы должны полностью изолировать себя от размещения структур в памяти. Их макет может измениться в любой будущей версии Swift, и вы не хотите, чтобы это сломало вашу программу.

Судя по комментариям, ваша проблема, похоже, не имеет абсолютно никакого отношения к расположению структур в памяти, а скорее к тому, как их переменные появляются при их регистрации. Это то, что вы можете определить сами:

struct User {
   let name: String
   let email: String
}

extension User: CustomStringConvertible {
    var description: String {
        return "your custom description"
    }
}
person Alexander    schedule 19.06.2017
comment
@Alexnder отличное объяснение. - person Oleg Gordiichuk; 19.06.2017

Хотя это ужасная идея, вы можете изменить вывод dump, добавив собственный Mirror:

extension User : CustomReflectable {
    var customMirror: Mirror {
        let children = DictionaryLiteral<String, Any>(
            dictionaryLiteral: ("email", self.email as Any), ("name", self.name as Any)
        )

        return Mirror(User.self, children: children)
    }
}

dump предназначен для отладки, и порядок свойств в выводе отладки не должен иметь большого значения.

person Sulthan    schedule 19.06.2017

Я не уверен на 100%, но я ожидаю, что дамп будет в том же формате, что и ваша структура.

struct User {
    var name:String?
    var email:String?
}

//Dump
~Name
~Email
person impression7vx    schedule 19.06.2017