SwiftCSV读取CSV数据及初步封装

最近在写一个记账的APP,原因是一直用的口袋记账不更新了,到现在还不支持全面屏,于是想着扒了它的素材,自己仿写一个,第一问题就是怎么导入以前几年的账单数据?目前口袋记账是可以导出账单发送到自己的邮箱的,但是邮箱收到的Excel文档,在查阅一些资料之后,发现可以通过WPS打开文档另存为CSV文件,然后在项目里读取CSV文件转成数组,然后转模型获得model对象,就可以展示在列表之中。

安装

CocoaPods

1
pod "SwiftCSV"

Carthage

1
github "swiftcsv/SwiftCSV"

读取CSV文件

首先我们要读入CSV文件,创建一个CSV对象, 然后我们从字符串字面量来创建一个CSV对象

1
let csv = CSV(string: "id,name,age\n1,Alice,18")

如果需要自定义分隔符可以这样

1
let tsv = CSV(string: "id\tname\tage\n1\tAlice\t18", delimiter: "\t")

我们可以传入路径及文件名来读取,可能会出错,所以使用try catch来捕获异常

1
2
3
4
5
6
// From a file (with errors)
do {
let csv = try CSV(name: "users.csv")
} catch {
// Catch errors or something
}

自定义换行符和编码方式

1
2
3
4
5
do {
let tsv = try CSV(name: "users.tsv", delimiter: tab, encoding: NSUTF8StringEncoding)
} catch {
// Error handling
}

数据读取

根据CSV的内容,写出如下的Model类

1
2
3
4
5
6
import Foundation
class SkillData:NSObject {
var id:String?
var name:String?
...
}

数据读取是一个需要时间的过程,所以我们用GCD来在异步线程进行读取,通过一个回调函数来获取我们的数据,并且封装一个通用的读取方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import Foundation
import SwiftCSV
class CSVReader {
/**
CSV读取

- parameter fileName: 文件名
- parameter completionHandle: completionHandle
*/
class func loadDataFromCSV<T:NSObject>(fileName:String,completionHandle:([T])->Void){
//异步读取
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
let filePath = NSBundle.mainBundle().pathForResource(fileName, ofType: "csv")
let csvURL = NSURL(fileURLWithPath: filePath!)
do{
let csv = try CSV(url: csvURL)
let dataArray = csv.rows.map({ (dic:[String:String]) -> T in
let data = T()
dic.forEach({ (key,value) in
data.setValue(value, forKey: key)
})
return data
})
dispatch_async(dispatch_get_main_queue(), {
completionHandle(dataArray)
})
}catch{
completionHandle([])
}
})
}
}

随后我们在一个Manager类中创建业务相关的读取方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import Foundation
class CSVDataManager{
static let sharedInstance = CSVDataManager()
var skillDataArray:[SkillData]?
func loadSkillData(completionHandle:([SkillData])->Void) {
if let data = skillDataArray{
completionHandle(data)
}else{
CSVReader.loadDataFromCSV("skill data", completionHandle: { (data:[SkillData]) in
self.skillDataArray = data
completionHandle(data)
})
}
}
}
0%