在 Swift 3 中本地保存自定义数组 Class

Saving Locally Array of Custom Class in Swift 3

我正在尝试在 xCode 8、Swift 3.

中本地保存名为 Lokacija(英语:Location)的自定义数组 Class

我尝试使用 UserDefault 保存它,但不幸的是它不适用于自定义 类。所以我找到了这篇文章:http://ioscake.com/how-to-archive-and-unarchive-custom-objects-in-swift-or-how-to-save-custom-object-to-nsuserdefaults-in-swift.html。我尝试了这两种解决方案,但其中 none 对我有用。顺便说一句,这篇文章是用 Swift 2.x 写的,正如我说的,我使用的是 Swift 3,所以我不得不翻译它。

我第一次尝试这个:

    class Lokacija: NSObject, NSCoding {

        var _name : String
        var _address : String
        var _long : Double
        var _lat : Double

        init(name : String, address : String, lat : Double, long : Double) {
            _name = name
            _address = address
            _lat = lat
            _long = long
            //day month year
        }

        func encode(with aCoder: NSCoder) {
            print("ENCODINGGG!!!")
            aCoder.encode(_name, forKey: "name")
            aCoder.encode(_address, forKey: "address")
            aCoder.encode(_long, forKey: "long")
            aCoder.encode(_lat, forKey: "lat")
        }
    }


//in custom .swift "Utils"

static func saveLocations(lokacije: [Lokacija]) {
    let dataBlob = NSKeyedArchiver.archivedData(withRootObject: lokacije)

    UserDefaults.standard.set(dataBlob, forKey: "lista")
    UserDefaults.standard.synchronize()
}

static func loadLocations() -> [Lokacija]? {
    guard let decodedDataBlob = UserDefaults.standard.object(forKey: "lista") as? Data, let loadedLocations = NSKeyedUnarchiver.unarchiveObject(with: decodedDataBlob) as? [Lokacija] else {
        return nil
    }

    return loadedLocations
}


    //on action
lista.append(selectedLoc)
Utils.saveLocations(lokacije: lista)

//in view did load
    if let listaBase = Utils.loadLocations() {
        lista = listaBase
        self.plannerTable.reloadData()
        print(listaBase.count)
        print(lista.count)
    } else {
        print("PATKA MOREEE!!!")
    }

问题是它没有在 listaBase 中写入任何内容,它是空的。 然后我尝试了第二种解决方案:

class Lokacija: NSObject, NSCoding {

    var _name : String
    var _address : String
    var _long : Double
    var _lat : Double

    init(name : String, address : String, lat : Double, long : Double) {
        _name = name
        _address = address
        _lat = lat
        _long = long
        //day month year
    }

    func encode(with aCoder: NSCoder) {
        print("ENCODINGGG!!!")
        aCoder.encode(_name, forKey: "name")
        aCoder.encode(_address, forKey: "address")
        aCoder.encode(_long, forKey: "long")
        aCoder.encode(_lat, forKey: "lat")
    }

    required convenience init?(coder aDecoder: NSCoder) {
        print("DECODEDDD!!!")
        guard let unName = aDecoder.decodeObject(forKey: "name") as? String, let unAddress = aDecoder.decodeObject(forKey: "address") as? String, let unLong = aDecoder.decodeObject(forKey: "long") as? Double, let unLat = aDecoder.decodeObject(forKey: "lat") as? Double
            else {
                return nil
        }
        self.init(name: unName, address: unAddress, lat: unLat, long: unLong)
    }

    private class func getFileUrl() -> NSURL {

        let documentsDirectory = FileManager().urls(for: (.documentDirectory), in: .userDomainMask).first!
        let archiveURL = documentsDirectory.appendingPathComponent("lista")

        return archiveURL as NSURL
    }

    class func saveLocations(locations: [Lokacija]){

        let success = NSKeyedArchiver.archiveRootObject(locations, toFile: Lokacija.getFileUrl().path!)
        if !success {
            print("failed to save")
        }

    }

    class func loadLocations() -> [Lokacija] {

        if let locBase = NSKeyedUnarchiver.unarchiveObject(withFile: Lokacija.getFileUrl().path!) as? [Lokacija] {
            return locBase
        }
        print("NIL")
        return [Lokacija]()
    }

}


//on action
    lista.append(selectedLoc)
    Lokacija.saveLocations(locations: lista)

    //on view did load      
    if Lokacija.loadLocations() != nil {
    let retrivedLocations = Lokacija.loadLocations()
    lista = retrivedLocations
    self.plannerTable.reloadData()
    print(retrivedLocations.count)
    print(lista.count)
}
else {
    print("FAILL!!!")
}

我遇到了完全相同的问题。

您解码 Double 值的方式有问题。将以下代码用于解码初始化程序,它将起作用:

required convenience init?(coder aDecoder: NSCoder) {
    print("DECODEDDD!!!")
    guard let unName = aDecoder.decodeObject(forKey: "name") as? String, let unAddress = aDecoder.decodeObject(forKey: "address") as? String else {
            return nil
    }

    let unLong = aDecoder.decodeDouble(forKey: "long")
    let unLat = aDecoder.decodeDouble(forKey: "lat")
    self.init(name: unName, address: unAddress, lat: unLat, long: unLong)
}