致命错误:in循环swift 3的索引超出范围

时间:2022-03-27 16:25:31

Im trying to create a save to pdf method using the simplePDF framework on Github. I have several arrays and have tried to use a for in loop. Its my first go at this, but I do not understand why I am getting fatal error: Index out of range. Here is my code.

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

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()

Any help is much appreciated. Thanks!

任何帮助深表感谢。谢谢!

3 个解决方案

#1


4  

Both answers are correct, but neither are ideal.

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

This would work:

这可行:

for index in 0..<count {

However, it's much better to use:

但是,使用它会好得多:

for index in Globals.datesArray.indicies

This way the range is created for you, and removes the potential for a typo (... instead of ..<)

这样就为你创建了范围,并消除了错字的可能性(...而不是.. <)

On a side note:

What concerns me is your use of 3 arrays to store related data. Wikipedia has a section on the pros and cons of parallel arrays. They really have no place in modern, high-level programming. They're cumbersome to work with, and very fragile. For example, if you add an element to the middle of datesArray and titleArray, but forget to add a description in descriptionArray, all of a sudden, you have mismatching between your dates/titles and descriptions.

我关心的是您使用3个数组来存储相关数据。*有一节关于并行数组的优缺点。他们在现代高级编程中确实没有地位。他们工作繁琐,而且非常脆弱。例如,如果将一个元素添加到datesArray和titleArray的中间,但忘记在descriptionArray中添加描述,那么突然之间,您的日期/标题和描述之间会有不匹配。

You should try using a class or struct. For example, you might want a struct declaration like this:

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

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

This lets you change a messy parallel structure like this:

这可以让你改变一个凌乱的并行结构,如下所示:

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

Into one like this:

进入这样一个:

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"
    ),
]

With this second declaration, all the information pertaining to a single Thing is stored cohesively. It lets you much more easily make additions/edits. No more counting elements to make sure they're lined up!

通过这个第二个声明,所有与单个事物有关的信息都是紧密地存储起来的。它可以让您更轻松地进行添加/编辑。没有更多计数元素,以确保他们排队!

With such a struct in place, your code can be written like this:

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

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()

That snippet uses enumerated(), which lets you iterate over elements and their index. This way, we don't have to subscript our array in the loop body.

该代码段使用enumerated(),它允许您迭代元素及其索引。这样,我们就不必在循环体中下标我们的数组。

However, the sum in this case will always be the sum of 0, 1, ... , count. This is equal to just (count * (count + 1)) / 2, so we can simplify the code further:

但是,在这种情况下,总和将始终是0,1,...,count的总和。这等于just(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

Now since we're not using index in the for loop body anymore, we can use regular iteration, without enumerated():

现在因为我们不再在for循环体中使用索引,所以我们可以使用常规迭代,而不使用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


2  

Alternatively to David's answer:

大卫回答的替代方案:

for index in 0...count {

could be

for index in 0..<count {

This will loop up until but not including count.

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

#3


1  

I think it should be let count = Globals.datesArray.count - 1. If Globals.count == 3, then index are [0,1,2], [3] would be out of range.

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

#1


4  

Both answers are correct, but neither are ideal.

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

This would work:

这可行:

for index in 0..<count {

However, it's much better to use:

但是,使用它会好得多:

for index in Globals.datesArray.indicies

This way the range is created for you, and removes the potential for a typo (... instead of ..<)

这样就为你创建了范围,并消除了错字的可能性(...而不是.. <)

On a side note:

What concerns me is your use of 3 arrays to store related data. Wikipedia has a section on the pros and cons of parallel arrays. They really have no place in modern, high-level programming. They're cumbersome to work with, and very fragile. For example, if you add an element to the middle of datesArray and titleArray, but forget to add a description in descriptionArray, all of a sudden, you have mismatching between your dates/titles and descriptions.

我关心的是您使用3个数组来存储相关数据。*有一节关于并行数组的优缺点。他们在现代高级编程中确实没有地位。他们工作繁琐,而且非常脆弱。例如,如果将一个元素添加到datesArray和titleArray的中间,但忘记在descriptionArray中添加描述,那么突然之间,您的日期/标题和描述之间会有不匹配。

You should try using a class or struct. For example, you might want a struct declaration like this:

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

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

This lets you change a messy parallel structure like this:

这可以让你改变一个凌乱的并行结构,如下所示:

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

Into one like this:

进入这样一个:

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"
    ),
]

With this second declaration, all the information pertaining to a single Thing is stored cohesively. It lets you much more easily make additions/edits. No more counting elements to make sure they're lined up!

通过这个第二个声明,所有与单个事物有关的信息都是紧密地存储起来的。它可以让您更轻松地进行添加/编辑。没有更多计数元素,以确保他们排队!

With such a struct in place, your code can be written like this:

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

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()

That snippet uses enumerated(), which lets you iterate over elements and their index. This way, we don't have to subscript our array in the loop body.

该代码段使用enumerated(),它允许您迭代元素及其索引。这样,我们就不必在循环体中下标我们的数组。

However, the sum in this case will always be the sum of 0, 1, ... , count. This is equal to just (count * (count + 1)) / 2, so we can simplify the code further:

但是,在这种情况下,总和将始终是0,1,...,count的总和。这等于just(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

Now since we're not using index in the for loop body anymore, we can use regular iteration, without enumerated():

现在因为我们不再在for循环体中使用索引,所以我们可以使用常规迭代,而不使用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


2  

Alternatively to David's answer:

大卫回答的替代方案:

for index in 0...count {

could be

for index in 0..<count {

This will loop up until but not including count.

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

#3


1  

I think it should be let count = Globals.datesArray.count - 1. If Globals.count == 3, then index are [0,1,2], [3] would be out of range.

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