Вы должны повторно модель данных, чтобы соответствовать его значение, а затем извлечь ваш TableView от этого. Таким образом, вы можете намного легче работать с данными, не беспокоясь о особых потребностях в отображении данных. Из вашего описания, у вас есть тип, Meal
который имеет [Ingredient]
:
struct Meal {
let name: String
let ingredients: [Ingredient]
}
(Ничего этого не было проверено, но оно должно быть довольно близко, чтобы исправить это все в Swift 3; Swift 2,2 очень похожа. .)
Ingredient
имеет имя и вид (мясо, углеводы и т.д.):
struct Ingredient {
enum Kind: String {
case meat
case carbs
var name: String { return self.rawValue }
}
let kind: Kind
let name: String
}
Теперь мы можем думать о вещах в терминах разделов, а не еды и ингридиентов и строк. Но, конечно, нам нужны разделы и строки для табличных представлений. Нет проблем. Добавьте их.
extension Meal {
// For your headers (these are sorted by name so they have a consistent order)
var ingredientSectionKinds: [Ingredient.Kind] {
return ingredients.map { $0.kind }.sorted(by: {$0.name < $1.name})
}
// For your rows
var ingredientSections: [[Ingredient]] {
return ingredientSectionKinds.map { sectionKind in
ingredients.filter { $0.kind == sectionKind }
}
}
}
Теперь мы можем легко захватить ингредиент для любого заданного индекса пути, и мы можем реализовать требование копирования на основе индекса путей:
extension Meal {
init(copyingIngredientsFrom meal: Meal, atIndexPaths indexPaths: [IndexPath]) {
let sections = meal.ingredientSections
self.init(name: meal.name, ingredients: indexPaths.map { sections[$0.section][$0.row] })
}
}
Теперь мы можем сделать все в одной строке вызывающего кода в контроллере табличного:
let newMeal = Meal(copyingIngredientsFrom: selectedMeal,
atIndexPaths: indexPathsForSelectedRows)
Мы не должны беспокоиться о том, какой раздел поместить каждый ингредиент в для копирования. Мы просто бросаем все ингредиенты в Пищу и позволяем им сортироваться позже.
Некоторые из этого кода очень неэффективны (он многократно переваривает некоторые моменты). Это будет проблемой, если списки ингредиентов могут быть длинными (но они, вероятно, нет), и могут быть оптимизированы, если необходимо, путем кэширования результатов или перепроектирования внутренних деталей реализации Meal. Но, начиная с четкой модели данных, код остается простым и простым, а не теряется во вложенных массивах в вызывающем коде.
Многомерные массивы очень сложны в использовании в Swift, потому что они не очень многомерны. Это всего лишь массивы массивов. Это означает, что каждая строка может иметь разное количество столбцов, что является общим источником сбоев в ошибках, когда люди бегут с концов данной строки.
Сначала вы должны получить раздел из своего источника. Поместите этот массив (массив строк в этом разделе) в переменную. Затем добавьте еду к этой переменной. А затем замените этот раздел в своем источнике на его собственный индекс. – pedrouan
Если вы только копируете выбранные ингредиенты, как вы планируете работать над разделами, если ничего не выбрано из раздела? Итак, если что-то из разделов 0, 2 и 3 выбрано, должны ли они быть в 0, 2 и 3 копии или в 0, 1 и 2?Понимание того, что представляют собой эти «разделы», и то, как вы сейчас выполняете цикл, вероятно, будет полезно здесь. Не совсем понятно, почему есть разделы и как они относятся к еде. Является ли еда состоящей из блюд, которые состоят из ингредиентов? –
@RobNapier Привет, Роб, спасибо за ответ. Таким образом, в основном каждый прием пищи получает такие ингредиенты, как курица-паста, это еда. Мягкие ингредиенты = [[цыпленок], [макаронные изделия], []], а затем разделы, которые [[мясо], [углеводы]] и т. Д., Но тогда есть дополнительные ингредиенты, такие как как грибы, перец, шпинат, и я хочу, чтобы люди могли выбирать эти или нет, чтобы они оставались в правой части копии. Извините, я должен был быть более ясным в начале. –