【问题标题】:How do I append to a section of an array? [[]]如何追加到数组的一部分? [[]]
【发布时间】:2016-08-30 12:40:07
【问题描述】:

我有一个数组,theMealIngredients = [[]]

我正在从当前的一顿饭中创建一个newMeal,我基本上是从表格视图的右侧部分和行中将所有选中标记的成分复制到其中。但是,当我使用append 时,它显然不知道该进入哪个部分,因为数组是多维的。它一直告诉我将其转换为NSArray,但这不是我想做的,我不认为。

我正在使用的当前行是:

newMeal.theMealIngredients.append((selectedMeal!.theMealIngredients[indexPath.section][indexPath.row])

【问题讨论】:

  • 首先您应该从您的源代码中获取该部分。将该数组(该部分中的行数组)放入变量中。然后将餐附加到该变量。然后在您的源代码中的正确索引处替换该部分。
  • 如果您只是复制选定的成分,如果没有选择任何部分,您希望这些部分如何工作?因此,如果选择了第 0、2 和 3 部分的内容,它们应该在副本的 0、2 和 3 中,还是在 0、1 和 2 中?了解这些“部分”是什么以及您当前的循环方式可能会对您有所帮助。目前尚不清楚为什么会有部分以及它们与膳食的关系。一顿饭是由食材组成的菜肴组成的吗?
  • @RobNapier 嗨 Rob,感谢您的回复。所以基本上每顿饭都有配料,比如鸡肉意大利面是meal1.theMealsIngredients = [[chicken],[pasta],[]],然后是[[meat],[carbs]]等部分,但还有一些可选的配料,比如如蘑菇、辣椒、菠菜,我希望人们能够选择或不选择这些,因此他们应该留在副本的正确部分。抱歉,我一开始应该更清楚。

标签: ios iphone swift uitableview tableview


【解决方案1】:

您应该重新建模您的数据以匹配其含义,然后从中提取您的表格视图。这样您就可以更轻松地处理数据,而不必为显示数据的特殊需求而烦恼。根据你的描述,你有一个类型,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 中很好地使用,因为它们并不是真正的多维数组。它们只是数组的数组。这意味着每一行可以有不同数量的列,当人们跑到给定行的末端时,这是崩溃错误的常见来源。

【讨论】:

  • 非常感谢您的帮助!这绝对令人难以置信,我可以看到你为我付出了很多努力,所以我真的很感激。我很新,所以周围有这样一个乐于助人的社区非常令人欣慰。我很快就想知道最后一行 self.init(ingredients: indexPaths.map {section[$0.section][$0.row] })。我收到“无法使用参数列表类型‘(成分:[成分]])’调用 Meal.init 的错误
  • 我忘记将名称传递给 init 函数。
  • 对不起,请您光顾我并解释一下我会怎么做? @RobNapier
  • 已修复。新行是:self.init(name: meal.name, ingredients: indexPaths.map { sections[$0.section][$0.row] })。当我最初在故事板中写这个时,我没有给饭菜名称,但是当我将它复制到答案中时,我添加了一个而不将它添加到 init。
  • 不幸的是,我仍然遇到了这个问题。我将 Meal 作为一个类,因为我希望它作为 NSObject 而不是可能是问题的结构。但是,我的课程是这样的: class Meal: NSObject { var mealTitle:String = "" var mealID:Int = 0 var mealImage = UIImage(named:"") var ingredients = [Ingredient]() } 和我的(方便)初始化程序是这样的:self.init(mealTitle:meal.mealTitle,mealID:meal.mealID,mealImage:meal.mealImage,成分:indexPaths.map {sections[$0.section][$0.row] })
猜你喜欢
  • 2016-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-20
  • 1970-01-01
  • 2016-08-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多