首页 > 解决方案 > 如何修复错误:线程 1:致命错误:索引超出范围”?

问题描述

url 从内容视图传递到第二个视图。然后将来自网站的 csv 内容传递到一个数组中。当我在其中输入 print(html2) 时,func path(in rect: CGRect) -> Path {它会在控制台中打印整个数组。

但是我只想要数组的特定部分。如您所见,我想将这些值添加到路径中。但是当我尝试只从数组中获取一个值(并将其转换为 Double)时,我得到错误“线程 1:致命错误:索引超出范围”我不明白为什么会发生这种情况,因为整个数组长于 3。

编辑: NIL 也打印在控制台中(来自guard let url = url else { return ["Nil"] },也许这与它有关。

这是网站,我从以下网址获取 csv 文件:https ://midcdmz.nrel.gov/apps/spa.pl?syear=2020&smonth=2&sday=1&eyear=2020&emonth=2&eday=1&otype=0&step=60&stepunit=1&hr=12&min= 0&sec=0&latitude=59&longitude=10.757933&timezone=1.0&elev=53&press=835&temp=10&dut1=0.0&deltat=64.797&azmrot=180&slope=0&refract=0.5667&field=0

控制台中的打印数组如下所示:

["日期 (M/D/YYYY),时间 (H:MM:SS),地心天顶角", "137.953123", "137.960600", "135.198176", "130.197954", "123.688949", "116.325934", " 108.624973“,“ 101.000252”,“ 93.815722”,“ 87.217417”,“ 82.082535”,“ 78.352650”,“ 78.352650”,“ 76.383830”,“ 76.35635”,“ 76.35635”,“ , "108.374905", "116.056945", "123.404211", "129.901657", "134.897752"]

这是我的代码:

func loadData(from url: URL?) -> Array<String> {
    guard let url = url else {
        return ["Nil"]
    }

    let html = try! String(contentsOf: url, encoding: String.Encoding.utf8)
    
    let parsedCSV: [String] = html.components(
        separatedBy: "00:00,"
    ).map{ $0.components(separatedBy: "\n")[0] }
    return parsedCSV
}

struct elevationFunction: Shape {
    
    var url1: URL?
    
    var html2: Array<String> { loadData(from: self.url1) }
    
    func path(in rect: CGRect) -> Path {

        var path = Path()

        path.move(to: CGPoint(x: 10, y: (125 - (90-Double(html2[3])!)))) // the error is here
        path.addLine(to: CGPoint(x: 120, y: (125 - (90-45))))
        path.addLine(to: CGPoint(x: 250, y: (125 - (90-Double(html2[3])!)))) // and here

        var scale = (rect.height / 350) * (9/10)
        var xOffset = (rect.width / 6)
        var yOffset = (rect.height / 6.5)

        return path.applying(CGAffineTransform(scaleX: scale, y: scale)).applying(CGAffineTransform(translationX: xOffset, y: yOffset))


    }
}

标签: swiftcsv

解决方案


数组索引从零开始,第三个元素是索引 2

path.move(to: CGPoint(x: 10, y: (125 - (90-Double(html2[2])!))))
path.addLine(to: CGPoint(x: 120, y: (125 - (90-45))))
path.addLine(to: CGPoint(x: 250, y: (125 - (90-Double(html2[2])!))))

我有一个似曾相识的感觉:我记得这段代码,我记得曾鼓励您使用URLSessionCSV 数据并将其解析为结构。

在操场上运行它

struct Zenith {
    let date : Date
    let angle : Double
}


func loadData(from urlString: String, completion: @escaping (Result<[Zenith],Error>) -> Void) {
    guard let url = URL(string: urlString) else {
        completion( .failure(URLError(.badURL))); return
    }
    
    let task = URLSession.shared.dataTask(with: url) {  data, _, error in
        if let error = error { completion(.failure(error)); return }
        let formatter = DateFormatter()
        formatter.locale = Locale (identifier: "en_US_POSIX")
        formatter.dateFormat = "M/d/yyyy H:mm:ss"
        let csvLines = String(data: data!, encoding: .utf8)!.components(separatedBy: .newlines).dropFirst()
        let zenithData = csvLines.compactMap { line -> Zenith? in
            let components = line.components(separatedBy: ",")
            guard components.count == 3 else { return nil }
            guard let date = formatter.date(from: components[0] + " " + components[1]),
                let angle = Double(components[2]) else { return nil }
            return Zenith(date: date, angle: angle)
        }
        completion(.success(zenithData))
    }
    task.resume()
}

let urlString = "https://midcdmz.nrel.gov/apps/spa.pl?syear=2020&smonth=2&sday=1&eyear=2020&emonth=2&eday=1&otype=0&step=60&stepunit=1&hr=12&min=0&sec=0&latitude=59&longitude=10.757933&timezone=1.0&elev=53&press=835&temp=10&dut1=0.0&deltat=64.797&azmrot=180&slope=0&refract=0.5667&field=0"

loadData(from: urlString) { result in
    switch result {

    case .success(let data): print(data)
    case .failure(let error): print(error)
    }
}

如果您异步加载数据,则无论如何都必须删除loadData()调用。Shape


推荐阅读