如何在文本文件中存储Swift自定义对象数组?

时间:2017-05-02 02:50:32

标签: arrays swift location

我有一个2D通用数组,其中大约有50个:

[string, string, string, string, double, double]

值的顺序相同,我有一个自定义类:

class tramStop {
    var tramDirection: String?
    var stopCode: String?
    var nameEnglish: String?
    var nameChinese: String?
    var latitude: Double?
    var longitude: Double?

    init(direction: String, code: String, nameEn: String, nameCn: String, lat: Double, lon: Double) {
        tramDirection = direction
        stopCode = code
        nameEnglish = nameEn
        nameChinese = nameCn
        latitude = lat
        longitude = lon
    }
}

我想将数组存储为文件中的自定义对象数组。我似乎无法弄清楚如何在不创建每次附加空数组的东西的情况下执行此操作。我觉得有一种简单(和正确)的方法可以做到这一点,但我无法弄明白。

最终我想做的是获取设备位置,找到最近的纬度和经度对象,并从中检索字符串。

2 个答案:

答案 0 :(得分:1)

首先,使用大写字母命名您的类和结构是Swift惯例。我建议使用结构而不是类。开始声明所有属性常量,并添加一个自定义初始值设定项,它将获取任何类型对象的数组(IMO应该使用字典作为源)。添加一个guard语句以确保数组计数等于6并正确初始化每个struct属性。要允许持久性,您可以添加计算属性来创建具有自己的信息的字典,并使用另一个属性将您的json对象转换为数据:

struct TramStop {
    let tramDirection: String
    let stopCode: String
    let nameEnglish: String
    let nameChinese: String
    let latitude: Double
    let longitude: Double

    init?(array: [Any]) {
        guard array.count == 6 else { return nil }

        tramDirection = array[0] as? String ?? ""
        stopCode      = array[1] as? String ?? ""
        nameEnglish   = array[2] as? String ?? ""
        nameChinese   = array[3] as? String ?? ""
        latitude      = array[4] as? Double ?? 0
        longitude     = array[5] as? Double ?? 0
    }

    init(_ dictionary: [String: Any]) {
        tramDirection = dictionary["tramDirection"] as? String ?? ""
        stopCode      = dictionary["stopCode"]      as? String ?? ""
        nameEnglish   = dictionary["nameEnglish"]   as? String ?? ""
        nameChinese   = dictionary["nameChinese"]   as? String ?? ""
        latitude      = dictionary["latitude"]      as? Double ?? 0
        longitude     = dictionary["longitude"]     as? Double ?? 0
    }

    var dictionary: [String: Any] {
        return [ "tramDirection" : tramDirection,
                 "stopCode"      : stopCode,
                 "nameEnglish"   : nameEnglish,
                 "nameChinese"   : nameChinese,
                 "latitude"      : latitude,
                 "longitude"     : longitude
        ]
    }

    var data: Data { return (try? JSONSerialization.data(withJSONObject: dictionary)) ?? Data() }
    var json: String { return String(data: data, encoding: .utf8) ?? String() }
}

创建一个结构来保存您的tramStops数组和正确的初始化器(array2D和jsonData):

struct Stops {

    let tramStops: [TramStop]

    init(_ array2D: [[Any]]) {
        tramStops = array2D.flatMap(TramStop.init)
    }

    init?(_ data: Data) {
        guard let array = (try? JSONSerialization.jsonObject(with: data)) as? [[String: Any]]
        else { return nil }
        tramStops = array.map(TramStop.init)
    }

    var array: [[String: Any]] {
        return tramStops.map{ $0.dictionary }
    }
    var data: Data {
        return (try? JSONSerialization.data(withJSONObject: array)) ?? Data()
    }
    var json: String {
        return String(data: data, encoding: .utf8) ?? String()
    }
}

游乐场测试

let array2D = [["a1", "a2", "a3", "a4", 1.0, 2.0],
           ["b1", "b2", "b3", "b4", 3.0, 4.0]]

let stops = Stops(array2D)
print(stops.json)           // "[{"nameEnglish":"a3","latitude":1,"tramDirection":"a1","longitude":2,"stopCode":"a2","nameChinese":"a4"},{"nameEnglish":"b3","latitude":3,"tramDirection":"b1","longitude":4,"stopCode":"b2","nameChinese":"b4"}]"

let jsonURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("TramStop.json")

stops.data    // 209 bytes
for tramStop in stops.tramStops {
    print(tramStop.dictionary)
    print(tramStop.stopCode)
    print(tramStop.nameEnglish)
    print(tramStop.nameChinese)
    print(tramStop.latitude)
    print(tramStop.longitude)
}

do {
    try stops.data.write(to: jsonURL)
    print("json data saved")
} catch  {
    print(error)
}

从fileURL读取json数据:

do {
    let data = try Data(contentsOf: jsonURL)
    print(String(data: data, encoding: .utf8) ?? "")
    if let stops = Stops(data) {
        for tramStop in stops.tramStops {
            print(tramStop.tramDirection)
            print(tramStop.stopCode)
            print(tramStop.nameEnglish)
            print(tramStop.nameChinese)
            print(tramStop.latitude)
            print(tramStop.longitude)
        }
    }
} catch {
    print(error)
}

答案 1 :(得分:0)

您需要循环遍历数组,获取每组6个元素并初始化tramStop以放入新的tramStop数组。或者,更好的是,首先初始化tramStops,而不创建临时阵列。

有多种方法可以保存到文件中,具体取决于您要对其执行的操作。 NSCoding可能适用,并且使您的类符合它是相当容易的。查看this文章。

编辑:以下是如何创建新的tramStop阵列:

var newArray: [tramStop] = []

for i in stride(from: 0, to: oldArray.count, by: 6) {
    newArray.append(tramStop(
        direction: oldArray[i] as! String,
        code: oldArray[i + 1] as! String,
        nameEn: oldArray[i + 2] as! String,
        nameCn: oldArray[i + 3] as! String,
        lat: oldArray[i + 4] as! Double,
        lon: oldArray[i + 5] as! Double
    ))
}

但是,正如我所说,我会研究如何完全消除oldArray

另外,当我提出NSCoding时,我不知道你想要一个文本文件,它不会给你一个文本文件。