【问题标题】:Fatal error: Index out of range for in loops swift 3致命错误:in loops swift 3 的索引超出范围
【发布时间】:2016-10-19 00:53:05
【问题描述】:

我正在尝试使用 Github 上的 simplePDF 框架创建保存到 pdf 的方法。我有几个数组并尝试使用 for in 循环。这是我的第一次尝试,但我不明白为什么会出现致命错误:索引超出范围。这是我的代码。

let A4paperSize = CGSize(width: 595, height: 842)
    let pdf = SimplePDF(pageSize: A4paperSize)
    pdf.setContentAlignment(.center)

    let count = Globals.datesArray.count
    var sum = 0

    for index in 0...count {
        pdf.addText(Globals.datesArray[index])
        pdf.addText(Globals.titleArray[index])
        pdf.addText(Globals.descriptionArray[index])
        sum += index
    }

    let pdfData = pdf.generatePDFdata()

非常感谢任何帮助。谢谢!

【问题讨论】:

  • 将for循环的条件改为for index in 0 ..< count

标签: ios arrays swift pdf for-loop


【解决方案1】:

两个答案都是正确的,但都不理想。

这可行:

for index in 0..<count {

但是,使用起来要好得多:

for index in Globals.datesArray.indicies

通过这种方式为您创建了范围,并消除了拼写错误的可能性(... 而不是..&lt;

附注:

我担心的是您使用 3 个数组来存储相关数据。维基百科有一个关于pros and cons of parallel arrays 的部分。它们在现代的高级编程中确实没有位置。它们使用起来很麻烦,而且非常脆弱。例如,如果您将一个元素添加到 datesArraytitleArray,但是忘记在descriptionArray 中添加描述,突然之间,您的日期/标题和描述不匹配。

您应该尝试使用class or struct。例如,您可能需要这样的结构声明:

struct Thing { //TODO: give me a name!
    let date: Date
    let title: String
    let description: String
}

这让你可以像这样改变一个凌乱的并行结构:

let datesArray = [date0, date1, date2]
let titlesArray = ["title0", "title1", "title2"]
let descriptionsArray = ["Description 0", "Description 1", "Description 2"]

变成这样:

let things = [
    Thing(
        date: date0,
        title: "title0"
        description: "Description 0"
    ),
    Thing(
        date: date1,
        title: "title1"
        description: "Description 1"
    ),
    Thing(
        date: date2,
        title: "title2"
        description: "Description 2"
    ),
]

使用第二个声明,与单个Thing 相关的所有信息都被内聚地存储。它使您可以更轻松地进行添加/编辑。无需再计算元素以确保它们排列整齐!

有了这样的结构,你的代码可以这样写:

let A4paperSize = CGSize(width: 595, height: 842)
let pdf = SimplePDF(pageSize: A4paperSize)
pdf.setContentAlignment(.center)

var sum = 0

for (index, thing) in things.enumerated() {
    pdf.addText(thing.date)
    pdf.addText(thing.title)
    pdf.addText(thing.description)
    sum += index
}

let pdfData = pdf.generatePDFdata()

那个 sn-p 使用enumerated(),它可以让你迭代元素及其索引。这样,我们就不必在循环体中下标我们的数组了。

但是,在这种情况下,sum 将始终是0, 1, ... , count 的总和。这等于只是(count * (count + 1)) / 2,所以我们可以进一步简化代码:

let A4paperSize = CGSize(width: 595, height: 842)
let pdf = SimplePDF(pageSize: A4paperSize)
pdf.setContentAlignment(.center)

for (index, thing) in things.enumerated() {
    pdf.addText(thing.date)
    pdf.addText(thing.title)
    pdf.addText(thing.description)
}

let pdfData = pdf.generatePDFdata()

let sum = (count * (count + 1)) / 2

现在由于我们不再在for 循环体中使用index,我们可以使用常规迭代,而无需enumerated()

let A4paperSize = CGSize(width: 595, height: 842)
let pdf = SimplePDF(pageSize: A4paperSize)
pdf.setContentAlignment(.center)

for index in things {
    pdf.addText(thing.date)
    pdf.addText(thing.title)
    pdf.addText(thing.description)
}

let pdfData = pdf.generatePDFdata()

let sum = (count * (count + 1)) / 2

【讨论】:

  • 这是最好的答案。
【解决方案2】:

替代大卫的回答:

for index in 0...count {

可能

for index in 0..<count {

这将循环直到但不包括计数。

【讨论】:

  • 感谢您的回答,这也有效。如果我能接受两个答案,我也会接受你的。
  • 只是除了你认为更好的那个。无论哪种方式都一样有效,所以你接受哪一种对我来说并不重要。
【解决方案3】:

我认为应该是let count = Globals.datesArray.count - 1。如果 Globals.count == 3,则索引为 [0,1,2],[3] 将超出范围。

【讨论】:

  • 这个答案不如WMios's answer 好,因为将Array.count - 1 放入一个名为count 的变量中更具误导性且可读性较差。
  • 我只是在解释错误“超出范围”的来源。最好的解决方案是“for myVar in Globals.datesArray {}”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-28
  • 1970-01-01
相关资源
最近更新 更多