将自定义 class 对象转换为 NSData
Converting custom class object into NSData
我有一个自定义 class,我想将其保存到 NSUserDefaults
。我被告知我需要将 class 对象转换为数据以便将其保存到 NSUserDefaults
。我发现了很多离散字符串或整数到 NSData
的例子,但没有关于自定义 class 到 NSData
的例子。我对 NSData
编码等的复杂性知之甚少。感谢任何帮助
编辑:虽然我知道这里有类似的答案,但其中 none 在 Swift 中。语言之间的翻译是可行的,但它非常乏味,有时甚至非常违反直觉。
这里有一个简单的例子供您参考:
//Custom class.
class Person: NSObject, NSCoding {
var name: String!
var age: Int!
required convenience init(coder decoder: NSCoder) {
self.init()
self.name = decoder.decodeObjectForKey("name") as! String
self.age = decoder.decodeObjectForKey("age") as! Int
}
convenience init(name: String, age: Int) {
self.init()
self.name = name
self.age = age
}
func encodeWithCoder(coder: NSCoder) {
if let name = name { coder.encodeObject(name, forKey: "name") }
if let age = age { coder.encodeObject(age, forKey: "age") }
}
}
//create an instance of your custom class.
var newPerson = [Person]()
//add some values into custom class.
newPerson.append(Person(name: "Leo", age: 45))
newPerson.append(Person(name: "Dharmesh", age: 25))
//store you class object into NSUserDefaults.
let personData = NSKeyedArchiver.archivedDataWithRootObject(newPerson)
NSUserDefaults().setObject(personData, forKey: "personData")
//get your object from NSUserDefaults.
if let loadedData = NSUserDefaults().dataForKey("personData") {
if let loadedPerson = NSKeyedUnarchiver.unarchiveObjectWithData(loadedData) as? [Person] {
loadedPerson[0].name //"Leo"
loadedPerson[0].age //45
}
}
已在 playground 上测试。
希望对您有所帮助。
这个link可以帮到你
重要的是你的 class 扩展 NSObject
和 NSCoding
,因为转换需要是它的 class,NSCoding
是一个接口来序列化和反序列化你的 class
Saving custom SWIFT class with NSCoding to UserDefaults
以下示例代码基于 Richie Rich 的回答(见上文)并通过了在此环境中的测试:
Xcode version 9.1 (9B55)
Swift version 4.0.2 (swiftlang-900.0.69.2 clang-900.0.38, Target: x86_64-apple-macosx10.9)
MacBook Air (11-inch, Mid 2012) with macOS High Sierra (version 10.13.1)
// Foundation is required to NSObject and NSCoding
import Foundation
// A custom class called Person with two properties (a string name and an
// integer age), that is a subclass of NSObject and adopts NSCoding protocol.
class Person: NSObject, NSCoding {
var name: String!
var age: Int!
// The convenience initializer for class Person
// Reference
// https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID217
convenience init(name: String, age: Int) {
// self.init() is the designated initializer for class Person.
// Reference
// https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID219
self.init()
self.name = name
self.age = age
}
// The initializer init(coder:) is required by NSCoding protocol
// Reference
// https://developer.apple.com/documentation/foundation/nscoding
// https://developer.apple.com/documentation/foundation/nscoding/1416145-init
required convenience init(coder aDecoder: NSCoder) {
self.init()
// as! is a type casting operator
// Reference
// https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID388
self.name = aDecoder.decodeObject(forKey: "name") as! String
self.age = aDecoder.decodeInteger(forKey: "age")
}
// The instance method encode(with:) is required by NSCoding protocol
// Reference
// https://developer.apple.com/documentation/foundation/nscoding
// https://developer.apple.com/documentation/foundation/nscoding/1413933-encode
func encode(with anEncoder: NSCoder) {
if let name = name {
anEncoder.encode(name, forKey: "name")
}
if let age = age {
anEncoder.encode(age, forKey: "age")
}
}
}
// Create an array (or, generally speaking, a collection) as a container to
// hold instances of our custom class type Person.
// Reference
// https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html
var anArrayOfPersons = [Person]()
print(anArrayOfPersons.count) // 0
// Add two instances into anArrayOfPersons.
// Reference
// https://developer.apple.com/documentation/swift/array
// https://developer.apple.com/documentation/swift/array/1538872-append
anArrayOfPersons.append(Person(name: "Cong", age: 33))
anArrayOfPersons.append(Person(name: "Sunny", age: 2))
// Archive anArrayOfPersons into NSData using NSKeyedArchiver.
// Reference
// https://developer.apple.com/documentation/foundation/nskeyedarchiver
// https://developer.apple.com/documentation/foundation/nskeyedarchiver/1413189-archiveddata
let dataToSave = NSKeyedArchiver.archivedData(withRootObject: anArrayOfPersons)
// Persist data. Storing anArrayOfPersons into UserDefaults as data.
// Reference
// https://developer.apple.com/documentation/foundation/userdefaults
// https://developer.apple.com/documentation/foundation/userdefaults/1414067-set
UserDefaults().set(dataToSave, forKey: "tagOfData")
// Take our stored data (in previous step) from UserDefaults using the key
// "personData". Optional binding is used to make sure the retrieved data is
// not nil.
// Reference
// https://developer.apple.com/documentation/foundation/userdefaults
// https://developer.apple.com/documentation/foundation/userdefaults/1409590-data
// https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID333
if let dataRetrieved = UserDefaults().data(forKey: "tagOfData"),
// Decode our instance objects from the retrieved data
// Reference
// https://developer.apple.com/documentation/foundation/nskeyedunarchiver
// https://developer.apple.com/documentation/foundation/nskeyedunarchiver/1413894-unarchiveobject
let anArrayOfPersonsRetrieved = NSKeyedUnarchiver.unarchiveObject(with: dataRetrieved) as? [Person] {
// See how many bytes the data we retrieved has.
print(dataRetrieved) // 393 bytes
// See if the name and age properties are the same as what we stored.
print(anArrayOfPersonsRetrieved[0].name) // "Cong"
print(anArrayOfPersonsRetrieved[0].age) // 45
print(anArrayOfPersonsRetrieved[1].name) // "Sunny"
print(anArrayOfPersonsRetrieved[1].age) // 2
}
我有一个自定义 class,我想将其保存到 NSUserDefaults
。我被告知我需要将 class 对象转换为数据以便将其保存到 NSUserDefaults
。我发现了很多离散字符串或整数到 NSData
的例子,但没有关于自定义 class 到 NSData
的例子。我对 NSData
编码等的复杂性知之甚少。感谢任何帮助
编辑:虽然我知道这里有类似的答案,但其中 none 在 Swift 中。语言之间的翻译是可行的,但它非常乏味,有时甚至非常违反直觉。
这里有一个简单的例子供您参考:
//Custom class.
class Person: NSObject, NSCoding {
var name: String!
var age: Int!
required convenience init(coder decoder: NSCoder) {
self.init()
self.name = decoder.decodeObjectForKey("name") as! String
self.age = decoder.decodeObjectForKey("age") as! Int
}
convenience init(name: String, age: Int) {
self.init()
self.name = name
self.age = age
}
func encodeWithCoder(coder: NSCoder) {
if let name = name { coder.encodeObject(name, forKey: "name") }
if let age = age { coder.encodeObject(age, forKey: "age") }
}
}
//create an instance of your custom class.
var newPerson = [Person]()
//add some values into custom class.
newPerson.append(Person(name: "Leo", age: 45))
newPerson.append(Person(name: "Dharmesh", age: 25))
//store you class object into NSUserDefaults.
let personData = NSKeyedArchiver.archivedDataWithRootObject(newPerson)
NSUserDefaults().setObject(personData, forKey: "personData")
//get your object from NSUserDefaults.
if let loadedData = NSUserDefaults().dataForKey("personData") {
if let loadedPerson = NSKeyedUnarchiver.unarchiveObjectWithData(loadedData) as? [Person] {
loadedPerson[0].name //"Leo"
loadedPerson[0].age //45
}
}
已在 playground 上测试。
希望对您有所帮助。
这个link可以帮到你
重要的是你的 class 扩展 NSObject
和 NSCoding
,因为转换需要是它的 class,NSCoding
是一个接口来序列化和反序列化你的 class
Saving custom SWIFT class with NSCoding to UserDefaults
以下示例代码基于 Richie Rich 的回答(见上文)并通过了在此环境中的测试:
Xcode version 9.1 (9B55)
Swift version 4.0.2 (swiftlang-900.0.69.2 clang-900.0.38, Target: x86_64-apple-macosx10.9)
MacBook Air (11-inch, Mid 2012) with macOS High Sierra (version 10.13.1)
// Foundation is required to NSObject and NSCoding
import Foundation
// A custom class called Person with two properties (a string name and an
// integer age), that is a subclass of NSObject and adopts NSCoding protocol.
class Person: NSObject, NSCoding {
var name: String!
var age: Int!
// The convenience initializer for class Person
// Reference
// https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID217
convenience init(name: String, age: Int) {
// self.init() is the designated initializer for class Person.
// Reference
// https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID219
self.init()
self.name = name
self.age = age
}
// The initializer init(coder:) is required by NSCoding protocol
// Reference
// https://developer.apple.com/documentation/foundation/nscoding
// https://developer.apple.com/documentation/foundation/nscoding/1416145-init
required convenience init(coder aDecoder: NSCoder) {
self.init()
// as! is a type casting operator
// Reference
// https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID388
self.name = aDecoder.decodeObject(forKey: "name") as! String
self.age = aDecoder.decodeInteger(forKey: "age")
}
// The instance method encode(with:) is required by NSCoding protocol
// Reference
// https://developer.apple.com/documentation/foundation/nscoding
// https://developer.apple.com/documentation/foundation/nscoding/1413933-encode
func encode(with anEncoder: NSCoder) {
if let name = name {
anEncoder.encode(name, forKey: "name")
}
if let age = age {
anEncoder.encode(age, forKey: "age")
}
}
}
// Create an array (or, generally speaking, a collection) as a container to
// hold instances of our custom class type Person.
// Reference
// https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html
var anArrayOfPersons = [Person]()
print(anArrayOfPersons.count) // 0
// Add two instances into anArrayOfPersons.
// Reference
// https://developer.apple.com/documentation/swift/array
// https://developer.apple.com/documentation/swift/array/1538872-append
anArrayOfPersons.append(Person(name: "Cong", age: 33))
anArrayOfPersons.append(Person(name: "Sunny", age: 2))
// Archive anArrayOfPersons into NSData using NSKeyedArchiver.
// Reference
// https://developer.apple.com/documentation/foundation/nskeyedarchiver
// https://developer.apple.com/documentation/foundation/nskeyedarchiver/1413189-archiveddata
let dataToSave = NSKeyedArchiver.archivedData(withRootObject: anArrayOfPersons)
// Persist data. Storing anArrayOfPersons into UserDefaults as data.
// Reference
// https://developer.apple.com/documentation/foundation/userdefaults
// https://developer.apple.com/documentation/foundation/userdefaults/1414067-set
UserDefaults().set(dataToSave, forKey: "tagOfData")
// Take our stored data (in previous step) from UserDefaults using the key
// "personData". Optional binding is used to make sure the retrieved data is
// not nil.
// Reference
// https://developer.apple.com/documentation/foundation/userdefaults
// https://developer.apple.com/documentation/foundation/userdefaults/1409590-data
// https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID333
if let dataRetrieved = UserDefaults().data(forKey: "tagOfData"),
// Decode our instance objects from the retrieved data
// Reference
// https://developer.apple.com/documentation/foundation/nskeyedunarchiver
// https://developer.apple.com/documentation/foundation/nskeyedunarchiver/1413894-unarchiveobject
let anArrayOfPersonsRetrieved = NSKeyedUnarchiver.unarchiveObject(with: dataRetrieved) as? [Person] {
// See how many bytes the data we retrieved has.
print(dataRetrieved) // 393 bytes
// See if the name and age properties are the same as what we stored.
print(anArrayOfPersonsRetrieved[0].name) // "Cong"
print(anArrayOfPersonsRetrieved[0].age) // 45
print(anArrayOfPersonsRetrieved[1].name) // "Sunny"
print(anArrayOfPersonsRetrieved[1].age) // 2
}