如何在Swift中使用NSCoder编码CGPoints数组?

时间:2015-12-08 21:19:19

标签: arrays swift

我正在尝试将我的自定义类的副本保存到文件中,我的类有两个CGPoints数组,我经常附加它们,它们看起来像这样:

class BlockAttributes: NSObject {
    var positions:[CGPoint] = []
    var spawns:[CGPoint] = []
}

就使用和访问课程而言,一切都很有效,但归档它并不起作用。我可以在其他类中存档Strings,Bools和Ints数组,但每次我尝试使用NSCoder编码我的CGPoints数组时,我的游戏都会失败。这是我的归档代码:

func encodeWithCoder(coder: NSCoder!) {
    coder.encodeObject(positions, forKey: "positions")
    coder.encodeObject(spawns, forKey: "spawns")
}

...

class ArchiveData: NSObject {

    var documentDirectories:NSArray = []
    var documentDirectory:String = ""
    var path:String = ""

    func saveData(data: BlockAttributes) {
        documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        documentDirectory = documentDirectories.objectAtIndex(0) as! String
        path = documentDirectory.stringByAppendingPathComponent("data.archive")

        if NSKeyedArchiver.archiveRootObject(data, toFile: path) {
            print("Success writing to file!")
        } else {
            print("Unable to write to file!")
        }
    }

    func retrieveData() -> NSObject {
        var dataToRetrieve = BlockAttributes()
        documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        documentDirectory = documentDirectories.objectAtIndex(0) as! String
        path = documentDirectory.stringByAppendingPathComponent("data.archive")
        if let dataToRetrieve2 = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as? BlockAttributes {
            dataToRetrieve = dataToRetrieve2 as BlockAttributes
        }
        return(dataToRetrieve)
    }
}

.... 并保存:

let archiveData = ArchiveData()
archiveData.saveData(myBlockActionsObject)

我甚至尝试创建自己的自定义类来保存CGPoints,我称之为MyCGPoint(我在某处读到了为某些数据类型创建自定义类可以解决一些NSCoder问题):

class MyCGPoint: NSObject {
    var x: CGFloat = 0.0
    var y: CGFloat = 0.0

    init(X: CGFloat, Y: CGFloat) {
        x = X
        y = Y
    }

    override init() {

    }
}

...

class BlockAttributes: NSObject {
    var positions:[MyCGPoint] = []
    var spawns:[MyCGPoint] = []
}

但是,唉,我仍然收到这个错误:

[Game.MyCGPoint encodeWithCoder:]:
unrecognized selector sent to instance 0x137f1d1a0 Game[20953:5814436]
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[Game.MyCGPoint encodeWithCoder:]:
unrecognized selector sent to instance 0x137f1d1a0'

知道如何使用encodeObject编码我的CGPoints / MyCGPoints数组吗?

2 个答案:

答案 0 :(得分:2)

CGPoint(及其Cocoa的双NSPoint)是结构,即值类型,因此您无法直接对它们进行编码。将它们包裹在NSValue

let positionValues = positions.map { NSValue(point:$0) }
let spawnValues    = spawns.map    { NSValue(point:$0) }

coder.encodeObject(positionValues, forKey: "positions")
coder.encodeObject(spawnValues, forKey: "spawns")

// Decode:
positons = (coder.decodeObjectForKey("positions") as! [NSValue]).map { $0.pointValue }
spawns   = (coder.decodeObjectForKey("spawns")    as! [NSValue]).map { $0.pointValue }

当您编写自定义包装类时,您必须使NSCoding符合NSValeuwidth:100%已经为您完成了免费。

答案 1 :(得分:2)

您可以将它们转换为字符串:

//To string
let point = CGPointMake(0, 0)
let string = NSStringFromCGPoint(point)
//Or if you want String instead of NSString
let string = String(point)

//From string
let point2 = CGPointFromString(string)