字典导致Swift中的索引超出范围错误

时间:2018-04-28 16:21:56

标签: swift uitableview

很抱歉,如果已经提出此问题,但我还没有找到解决方法。我是Swift的新手所以请耐心等待。我无法弄清楚为什么我一直收到线程1:致命错误:索引超出范围的错误。我之前使用过相同的方法来显示我之前从未遇到过问题的txt文件,所以这是第一次。我正在尝试将坐标显示为文本详细信息,日期和时间作为单元格本身的文本。

Date and Time

Latitude, Longitude

如上所述(想象一下它在一个单元格中)

以下是我的程序代码

import UIKit
import MapKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {



//Array to store the list
var storeCoordinates = [String:  String]()
var arrayClient = NSMutableArray()
var readings: [String] = [" "]

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.



    //Get path of where the file is
    let path = Bundle.main.path(forResource: "gps_coords", ofType: "csv")

    //Use filemanager to check if the file exist to avoid crashing if it doesn't exist
    let fileMgr = FileManager.default

    //Display the number of line counts we have
    if fileMgr.fileExists(atPath: path!){
        do {
            let fulltext = try String(contentsOfFile: path!, encoding: String.Encoding.utf8)

            readings = fulltext.components(separatedBy: "\n") as [String]

            for i in 0..<readings.count{
                let listData = readings[i].components(separatedBy: ";") as [String]

                storeCoordinates["Latitude"] = "\(listData[0])"
                storeCoordinates["Longitude"] = "\(listData[1])"
                storeCoordinates["DateAndTime"] = "\(listData[2])"

                arrayClient.add(storeCoordinates)
            }
        } catch let error as NSError {
            print("Error: \(error)")
        }
    }
    self.title = "Number of entries: \(arrayClient.count)"
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return arrayClient.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier", for: indexPath)

    let client = arrayClient[indexPath.row] as AnyObject

    cell.textLabel?.text = "\(client.object(forKey: "DateAndTime")!)"
    cell.detailTextLabel?.text = "\(client.object(forKey: "Latitude")!) \(client.object(forKey: "Longitude")!)"

    return cell

}

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

}

我遇到的错误是storeCoordinates["Latitude"] = "\(listData[0])" 使用断点,它显示Latitude值与Longitude和DateAndTime一起不为空,但如果我尝试在模拟器中运行应用程序,则会出现错误线程1:致命错误:索引超出范围。到目前为止,没有运气试图弄清楚如何解决这个问题。如果你能帮我搞清楚,那对我来说意味着很多。拜托,谢谢你。

2 个答案:

答案 0 :(得分:0)

正如 @vadian 中提到的评论一样,您不可能获得第0个索引。但是你添加了一些支票。

按以下方式更新您的代码:

有些更新 -

  

使用基于swift的数组[[String: String]]而不是NSMutableArray

     

为每个循环周期初始化storeCoordinates并检查您的listData是否包含3件以上的商品

class AViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    //Array to store the list
    var arrayClient = [[String: String]]()
    var readings: [String] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        //Get path of where the file is
        let path = Bundle.main.path(forResource: "gps_coords", ofType: "csv")

        //Use filemanager to check if the file exist to avoid crashing if it doesn't exist
        let fileMgr = FileManager.default

        //Display the number of line counts we have
        if fileMgr.fileExists(atPath: path!){
            do {
                let fulltext = try String(contentsOfFile: path!, encoding: String.Encoding.utf8)

                readings = fulltext.components(separatedBy: "\n") as [String]

                for i in 0..<readings.count {
                    // Check if you can get data from `readings[i]`
                    let listData = readings[i].components(separatedBy: ";") as [String]
                    if listData.count == 3 {
                        var storeCoordinates = [String: String]()
                        storeCoordinates["Latitude"] = "\(listData[0])"
                        storeCoordinates["Longitude"] = "\(listData[1])"
                        storeCoordinates["DateAndTime"] = "\(listData[2])"
                        arrayClient.append(storeCoordinates)
                    }
                }
            } catch let error as NSError {
                print("Error: \(error)")
            }
        }
        self.title = "Number of entries: \(arrayClient.count)"
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return arrayClient.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier", for: indexPath)

        let client = arrayClient[indexPath.row]
        if let dateTime = client["DateAndTime"], let latitude = client["DateAndTime"], let longitude = client["DateAndTime"] {
            cell.textLabel?.text = "\(dateTime)"
            cell.detailTextLabel?.text = "\(latitude) \(longitude)"
        }

        return cell
    }
}

答案 1 :(得分:0)

我认为不可靠的CSV格式是问题的根源。

这是一个使用更好格式(JSON)和更强大的数据源的快速教程。

第1部分:将CSV转换为JSON

  1. 创建新的空白游乐场(按⌥⇧⌘N)平台 macOS
  2. ⌘0显示Playground的项目导航器。
  3. ⌥-drag 将CSV文件从主项目的项目导航器拖放到Playground的Resources文件夹中。
  4. 将以下代码粘贴到Playground中,它基于您的代码来解析CSV。它将CSV转换为JSON并在桌面上创建文件gps_coords.json。如果缺少任何字段,您将收到致命错误。

    struct Coordinate : Encodable {
        let latitude, longitude, dateAndTime : String
    }
    
    let url = Bundle.main.url(forResource: "gps_coords", withExtension: "csv")!
    let fulltext = try! String(contentsOf: url, encoding: .utf8)
    let lines = fulltext.components(separatedBy: .newlines)
    let coordinates = lines.map { paragraph -> Coordinate in
        let components = paragraph.components(separatedBy: ";")
        if components.count != 3 { fatalError("Each line must contain all three fields")}
        return Coordinate(latitude: components[0], longitude: components[1], dateAndTime: components[2])
    }
    do {
        let data = try JSONEncoder().encode(coordinates)
        let homeURL = URL(fileURLWithPath: NSHomeDirectory())
        let destinationURL = homeURL.appendingPathComponent("Desktop/gps_coords.json")
        try data.write(to: destinationURL)
    } catch { print(error) }
    
  5. 第2部分:实施新文件

    1. 关闭游乐场。它不再需要了。
    2. 将新文件从桌面拖到项目导航器中(确保选中Copy If Needed)。
    3. ViewController课程更改为

      import UIKit
      import MapKit
      
      struct Coordinate : Decodable {
          let latitude, longitude, dateAndTime : String
      }
      
      class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
      
          var arrayClient = [Coordinate]()
      
          override func viewDidLoad() {
              super.viewDidLoad()
              let url = Bundle.main.url(forResource: "gps_coords", withExtension: "json")!
              let data = try! Data(contentsOf: url)
              arrayClient = try! JSONDecoder().decode([Coordinate].self, from: data)
              self.title = "Number of entries: \(arrayClient.count)"
              tableView.reloadData()
          }
      
          func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
              return arrayClient.count
          }
      
          func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
              let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier", for: indexPath)
              let client = arrayClient[indexPath.row]
      
              cell.textLabel?.text = client.dateAndTime
              cell.detailTextLabel?.text = client.latitude + " " + client.longitude
              return cell           
          }
      }
      

      注意: UITableView插座缺失,我添加了重新加载数据的行。还要确保在Interface Builder中将delegatedatasource从表格视图连接到ViewController

    4. 删除CSV文件。

    5. 新代码使用结构Coordinate作为数据源,并使用JSONDecoder非常方便地解码JSON。请注意丢失的类型强制转换和繁琐的密钥订阅以从字典中获取值。