Использование обобщений типов при попытке реализовать класс View-like в SwiftUI - PullRequest
0 голосов
/ 31 марта 2020

Я собираюсь построить IndexedList, который будет работать точно так же, как SwiftUI List View, но обеспечивает закрытие с (element, index) -> RowContent по сравнению с текущим (element) -> RowContent.

Одна вещь, которую я я не нашел, как вы можете назначить init() обобщение экземпляру класса, когда вы не знаете тип на уровне класса.

Если вы посмотрите на одну из List подписи инициализации View, вы можете видеть, что он использует локальные дженерики:

 public init<Data, RowContent>(_ data: Data, selection: Binding<Set<SelectionValue>>?, @ViewBuilder rowContent: @escaping (Data.Element) -> RowContent) where Content == ForEach<Data, Data.Element.ID, HStack<RowContent>>, Data : RandomAccessCollection, RowContent : View, Data.Element : Identifiable

Однако Data является типом generi c на уровне метода init(), как вы можете определить его на уровне класса, чтобы вы могли сделать self.data = data?

Пробовал Data и RandomAccessCollection:

struct IndexedList<SelectionValue, Content>: View where SelectionValue: Hashable, Content: View {
  let data: RandomAccessCollection // <- type issue
  let selection: Binding<Set<SelectionValue>>?
  let rowContent: (Data.Element) -> View // <- type issue
  var body: some View {
    let withIndex = self.data.enumerated().map({ $0 })
    return List(withIndex, id: \.element.id) { index, element in
      self.rowContent(index, element)
    }
  }
  public init<Data, RowContent>(_ data: Data, selection: Binding<Set<SelectionValue>>?, @ViewBuilder rowContent: @escaping (Data.Element, index: number) -> RowContent) where Content == ForEach<Data, Data.Element.ID, HStack<RowContent>>, Data : RandomAccessCollection, RowContent : View, Data.Element : Identifiable {
    self.data = data
    self.selection = selection
    self.rowContent = rowContent
  }
}

Но это не работает!

Ответы [ 2 ]

0 голосов
/ 31 марта 2020

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

struct IndexedList<
  Data: RandomAccessCollection,
  SelectionValue: Hashable,
  HStackContent: View
>: View
where Data.Element: Hashable & Identifiable {
  typealias Selection = Binding< Set<SelectionValue> >?
  typealias RowContent =
    (EnumeratedSequence<[Data.Element]>.Element)
    -> ForEach< Data, Data.Element.ID, HStack<HStackContent> >

  let data: Data
  let selection: Selection
  let rowContent: RowContent

  var body: some View {
    List(
      Array( data.enumerated() ),
      id: \.element,
      rowContent: rowContent
    )
  }

  public init(
    _ data: Data,
    selection: Selection,
    @ViewBuilder rowContent: @escaping RowContent
  )  {
    self.data = data
    self.selection = selection
    self.rowContent = rowContent
  }
}
0 голосов
/ 31 марта 2020

Не думаете ли вы, что ниже одной строки кода, который делает то же самое, просто проще ...

List(Array(items.enumerated()), id: \.element.id) { i, item in
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...