1. Если вы go в документации Apple для List
, в вашем вопросе есть немного больше информации о функции init
.
Здесь он отформатирован ниже подходит:
// List declaration
struct List<SelectionValue, Content>
where
SelectionValue : Hashable,
Content : View
// init declaration
init<Data, ID, RowContent>(
_ data: Data,
id: KeyPath<Data.Element, ID>,
selection: Binding<SelectionValue?>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent
) where
Content == ForEach<Data, ID, HStack<RowContent>>,
Data : RandomAccessCollection,
ID : Hashable,
RowContent : View
Это немного сложно, я согласен.
2. Угловые скобки используются для Generics . Это большой список c, который вам нужно знать о языке, чтобы продолжить.
Вкратце, Generi c - это заполнитель для возможного конкретного типа (String
, Int
, HStack
, Foo
, et c ...), который будет
Общий c тип заполнителя может быть ограничен для соответствия определенному протоколу c или наследовать от определенного класса . Это делается с помощью предложения where
.
3. Итак, один за другим:
Список имеет 2 заполнителя: SelectionValue
и Content
(может были названы как угодно, например <T, U>
):
struct List<SelectionValue, Content>
, и эти заполнители ограничены:
where
SelectionValue : Hashable,
Content : View
Они должны соответствовать Hashable
и View
соответственно .
Итак, в основном, когда вы видите Content
в определениях функций, это означает, что это может быть любая реализация View
. То же самое для SelectionValue
.
Продолжаем:
init<Data, ID, RowContent>
В дополнение к заполнителям, которые объявляет List
, init
также обобщается примерно на три дополнительных заполнителя: Data
, ID
и RowContent
, также с ограничениями:
where
Content == ForEach<Data, ID, HStack<RowContent>>,
Data : RandomAccessCollection,
ID : Hashable,
RowContent : View
Content
: должно быть ForEach
(определенного типа c). На самом деле вы не должны об этом заботиться, поскольку Content
не является ни одним из типов параметров init
Data
: любого типа, соответствующего RandomAccessCollection
, например Array
ID
: любой тип, соответствующий Hashable
RowContent
: Любой тип, соответствующий View
- практически любой вид
4. Сейчас , для параметров:
init<Data, ID, RowContent>(
_ data: Data,
id: KeyPath<Data.Element, ID>,
selection: Binding<SelectionValue?>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent
)
_ data
: это немаркированный параметр типа Data
, который (см. выше) что-то вроде массива
id
: это KeyPath
(также topi c Swift , который вам следует изучить), но в двух словах, выражение, указывающее на свойство объекта. В этом случае объект является элементом Data
(например, массив), а свойство - любое ID
(также известное как Hashable
).
selection
: это Binding
. Подробнее о привязках в SwiftUI и о оболочках свойств (привязка доступна через @State
оболочку свойств ). Но в основном это позволяет вам передавать вашу переменную состояния в представление, чтобы оно могло изменять ее, не владея данными. Привязка идет рука об руку с обернутым свойством @State
, получая доступ к его прогнозируемому значению с префиксом $
. См. Пример ниже.
rowContent
: это закрытие, которое принимает элемент указанного Data
(например, элемент массива) и возвращает RowContent
(также известный как View
). На данный момент не беспокойтесь о @ViewBuilder
.
5. Пример:
let strArray = ["One", "Two", "Three"]
@State var selection: String? = 0
// ...
List(strArray, id: \.self, selection: $selection, rowContent: { str in
return Text(str)
})
strArray
: это массив, поэтому он удовлетворяет общим c ограничение Data
\.self
: выражение ключевого пути, указывающее на себя (строка, которая соответствует Hashable)
selection
: привязано к переменной состояния selection
. $selection
- это прогнозируемое значение этой переменной, которое SwiftUI удобно преобразовал в тип привязки.
rowContent
: закрывает каждый элемент массива и возвращает вид Text
.