Converting custom class object into NSData
Here is one simple example for you:
//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
}
}
Tested with playground.
Hope this helps.
Convert a custom object to Data to be saved in NSUserDefauts
The issue there. is that you are mixing up Codable with NSCoding. To use NSKeyedArchiver's archivedData method you need to have a class that conforms to NSCoding. In you case you have a structure that conforms to Codable so you need to use JSONEncoder encode method. Note: Your equatable method declaration was wrong:
struct BallPark: Codable, Equatable {
static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.id == rhs.id
}
let id: String
let name: String?
let location: VenueCoordinates?
let mapEnabled: Bool?
let facilityStatus: String?
}
struct VenueCoordinates: Codable {
let latitude: String?
let longitude: String?
var lat: Double? {
guard let latitud = latitude else { return nil}
return Double(latitud)
}
var lon: Double? {
guard let longitude = longitude else { return nil}
return Double(longitude)
}
}
let bestBallParkToSave = BallPark.init(id: "1", name: "Steve", location: .init(latitude: "20.0", longitude: "40.0"), mapEnabled: true, facilityStatus: "a status")
do {
let encodedBestBallPark = try JSONEncoder().encode(bestBallParkToSave)
UserDefaults.standard.set(encodedBestBallPark, forKey: "favoriteBallPark")
if let ballParkData = UserDefaults.standard.data(forKey: "favoriteBallPark") {
let loadedBallPark = try JSONDecoder().decode(BallPark.self, from: ballParkData)
print(loadedBallPark) // BallPark(id: "1", name: Optional("Steve"), location: Optional(VenueCoordinates(latitude: Optional("20.0"), longitude: Optional("40.0"))), mapEnabled: Optional(true), facilityStatus: Optional("a status"))
}
} catch {
print(error)
}
You can also make your life easier extending UserDefaults and create customs encoding and decoding methods:
extension UserDefaults {
func decodeObject<T: Decodable>(forKey defaultName: String, using decoder: JSONDecoder = .init()) throws -> T {
try decoder.decode(T.self, from: data(forKey: defaultName) ?? .init())
}
func encode<T: Encodable>(_ value: T, forKey defaultName: String, using encoder: JSONEncoder = .init()) throws {
try set(encoder.encode(value), forKey: defaultName)
}
}
Usage:
let bestBallParkToSave = BallPark(id: "1", name: "Steve", location: .init(latitude: "20.0", longitude: "40.0"), mapEnabled: true, facilityStatus: "a status")
do {
try UserDefaults.standard.encode(bestBallParkToSave, forKey: "favoriteBallPark")
let loadedBallPark: BallPark = try UserDefaults.standard.decodeObject(forKey: "favoriteBallPark")
print(loadedBallPark) // BallPark(id: "1", name: Optional("Steve"), location: Optional(VenueCoordinates(latitude: Optional("20.0"), longitude: Optional("40.0"))), mapEnabled: Optional(true), facilityStatus: Optional("a status"))
} catch {
print(error)
}
How can I store an custom class as Data
Define a custom object which conforms to Codable
. A simple example:
struct MyObject: Codable {
var something: String
}
And when you want to save it to UserDefaults, just encode
it:
do {
let encoded = try JSONEncoder().encode(MyObject(something: "String"))
UserDefaults.standard.set(encoded, forKey: "kSavedObject")
} catch {
print(error)
}
If you want to retrieve it, you can use decode
:
if let data = UserDefaults.standard.data(forKey: "kSavedObject") {
do {
let myRetrievedObject = try JSONDecoder().decode(MyObject.self, from: data)
} catch {
print(error)
}
}
converting custom object to NSData Swift
if your Enum
is like this PieceType
and type is Int
enum PieceType : Int {
case empty
case notEmpty
}
Then write encode
and decode
method like this way
required init(coder aDecoder: NSCoder) {
isSelected = aDecoder.decodeBool(forKey: "isSelected")
type = PieceType(rawValue: aDecoder.decodeObject(forKey: "type") as! Int)!
isWhite = aDecoder.decodeBool(forKey: "isWhite")
isFirstMove = aDecoder.decodeBool(forKey: "isFirstMove")
symbol = aDecoder.decodeObject(forKey: "symbol") as! String
position = aDecoder.decodeObject(forKey: "position") as! (Int, Int)
}
func encode(with aCoder: NSCoder) {
aCoder.encode(isSelected, forKey: "isSelected")
aCoder.encode(type.rawValue, forKey: "type")
aCoder.encode(isWhite, forKey: "isWhite")
aCoder.encode(isFirstMove, forKey: "isFirstMove")
aCoder.encode(symbol, forKey: "symbol")
aCoder.encode(position.row, forKey: "position.row")
aCoder.encode(position.col, forKey: "position.col")
}
i have check bellow code and it work's
let pice = Piece(isSelected: true, type: .empty, isWhite: true, isFirstMove: true, symbol: "Test", position: (2, 10))
let pieceData = NSKeyedArchiver.archivedData(withRootObject:pice)
print(pieceData)
And Out put is
386 bytes
ios swift, How to convert 'object to nsdata'
Xcode 8 (Swift 3) Playground:
class PacketHeader: NSObject, NSCoding {
var ver: UInt8 = 0
var len: UInt32 = 0
override init() {
super.init()
}
required init(coder aDecoder: NSCoder) {
if let ver = aDecoder.decodeObject(forKey: "ver") as? NSNumber {
self.ver = ver.uint8Value
}
if let len = aDecoder.decodeObject(forKey: "len") as? NSNumber {
self.len = len.uint32Value
}
}
func encode(with aCoder: NSCoder) {
aCoder.encode(NSNumber(value: ver), forKey: "ver")
aCoder.encode(NSNumber(value: len), forKey: "len")
}
}
let data = PacketHeader()
data.ver = 10
data.len = 8
let savedData = NSKeyedArchiver.archivedData(withRootObject: data)
let obj = NSKeyedUnarchiver.unarchiveObject(with: savedData) as? PacketHeader
obj?.ver
obj?.len
How to convert document to a custom object in Swift 5?
After contacting the firebase team, I found the solution I was looking for. It turns out I have to do import FirebaseFirestoreSwift
explicitly instead of just doing import Firebase
. The error will disappear after this. (And of course you'll need to add the pod to your podfile first:D)
How to convert an array of multiple object types to JSON without missing any object attribute in Swift?
class SUVCar: Car
{
enum SUVCarKeys: CodingKey {
case weight
}
var weight: Int
init(_ weight: Int)
{
self.weight = weight
super.init(brand: "MyBrand")
}
override func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: SUVCarKeys.self)
try container.encode(weight, forKey: .weight)
try super.encode(to: encoder)
}
}
If you augment the subclass's implementation of encode then you can add in additional properties
Related Topics
Realm: Predicate Returning Lazyfiltercollection - How to Convert to Results<T>
Swift Combine How Set<Anycancellable> Works
Destructuring Tuple of Tuple in Closure
How to Put View on Top of All Other Views in Swiftui
Viewwilllayoutsubviews in Swift
Scrolltoitem at Indexpath at .Top Hides Cell Under Header When Sectionheaderspintovisiblebounds
Swift Navigation Bar Item Not Calling Action
Why Would One Use Nested Classes
Can't Upload .Ipa from Xcode 8, "The Info.Plist Indicates a iOS App, But Submitting a Pkg or Mpkg."
How to Draw a Line Between Two Points Over an Image in Swift 3
Shorthand for Wrapping a Swift Variable in an Optional
Passing in Variable Number of Args from One Function to Another in Swift
Issue with Returning a Directory Enumerator from Nsfilemanager Using Enumeratoraturl in Swift
Switch to Match Multiple Cases from Optionsettype
A Concise Way to Not Execute a Loop Now That C-Style for Loops Are Going to Be Removed from Swift 3
Close UIdatepicker After Selection When Style Is .Compact
Using Associatedtype in a Delegate Protocol for a Generic Type