Как использовать SwiftUI ForEach со словарем [customEnum: customStrut] - получение ошибки «соответствовать« RandomAccessCollection »» - PullRequest
2 голосов
/ 26 апреля 2020

Как я могу исправить этот код после сбоя сборки? В основном желая использовать ForEach для перебора словаря, основанного на [customEnum: customStrut].

В противном случае, если это проблематично c другой способ добиться того, что поддерживает SwiftUI?

Ошибки

Ссылка инициализатора 'init (_: id: content :)' на 'ForEach' требует, чтобы '[GCFilterViewOptions.FilterOptions: GCFilterViewOptions.FilterOptionValues]' соответствовал 'RandomAccessCollection '

Type' (ключ: GCFilterViewOptions.FilterOptions, значение: GCFilterViewOptions.FilterOptionValues) 'не может соответствовать' Hashable '; только типы struct / enum / class могут соответствовать протоколам

Код

import SwiftUI

struct GCFilterViewOptions: View {
    enum FilterOptions {
        case NewLine
        case Comma
        case Space
    }
    struct FilterOptionValues {
        var title : String
        var selected : Bool
    }
    var filterSelections : [FilterOptions : FilterOptionValues] = [
        FilterOptions.NewLine : FilterOptionValues(title: "New Line", selected: true),
        FilterOptions.Comma : FilterOptionValues(title: "Comma", selected: true),
        FilterOptions.Space : FilterOptionValues(title: "Space", selected: false)
    ]

    var body : some View {
        HStack {
            ForEach(filterSelections, id:\.self) { filterOption in.  // ** ERRORS HERE **
                Text("TBD")
                // Will be putting checkboxes here - i.e. so can chose which ones 
            }
        }
    }
}

Ответы [ 2 ]

1 голос
/ 26 апреля 2020

Поскольку словарь состояний не является коллекцией, поддерживающей произвольный доступ, поэтому его нельзя использовать непосредственно в ForEach, здесь возможен подход

HStack {
    ForEach(Array(filterSelections.keys.enumerated()), id:\.element) { _, key in
        Text("TBD \(self.filterSelections[key]?.title ?? "")")
        // Will be putting checkboxes here - i.e. so can chose which ones
    }
}
0 голосов
/ 26 апреля 2020

Циклы ForEach поддерживают только структуры данных с поддержкой RandomAccess (документация Apple о том, что отличает RandomAccessCollection).

Если вам действительно не нужна структура словаря, вы можете использовать простую структуру. Это в основном то же самое, что и у вас, но перечисление вложено в него и является свойством:

struct FilterOption {
    enum FilterOptionType {
        case newLine
        case comma
        case space
    }

    var type: FilterOptionType
    var title: String
    var selected: Bool
}

var filterSelection: [FilterOption] = [
    FilterOption(type: .newLine, title: "New line", selected: true),
    FilterOption(type: .comma, title: "Comma", selected: false),
    FilterOption(type: .space, title: "Space", selected: true),
]

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

enum FilterOption: String {
    case newLine
    case comma
    case space
}
struct FilterOptionValue {
    var title: String
    var selected: Bool
}
var filterSelection: [FilterOption: FilterOptionValue] = [
    .newLine: FilterOptionValue(title: "New Line", selected: true),
    .comma: FilterOptionValue(title: "Comma", selected: true),
    .space: FilterOptionValue(title: "Space", selected: false)
]

// Guarantees a stable print order
for option in filterSelection.keys.sorted(by: { $0.rawValue < $1.rawValue }) {
    let optionValue = filterSelection[key]!
    print(option, optionValue)
}

Обратите внимание, что в перечислениях Swift регистры нижнего регистра как свойства есть. Только типы начинаются с заглавной буквы (newLine, а не NewLine).

Кроме того, имя типа enum должно быть в единственном числе, так как при создании экземпляра они представляют только один параметр. Используйте FilterOption вместо FilterOptions.

То же самое для filterSelections, который должен быть единичным, так как выделение уже содержит несколько элементов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...