I am using CoreData in my application. I created an entity which has two attributes. One is Int type and second one is Transformable Type. I am able to save my record successfully. But when I try to fetch, It get crash. And one more thing, everything is working fine without using Transformable type. What could be the reason? Is that Transformable Type? And If yes then what is the solution?
func saveUserInfoInDatabase(userDetails: FleetInfoDetails) {
self.deleteUserInfoFromDatabase()
let entityDescription = NSEntityDescription.entityForName("UserInfo", inManagedObjectContext: self.userInfoObjectContext)
let data = UserInfo(entity: entityDescription!, insertIntoManagedObjectContext: self.userInfoObjectContext)
print(userDetails)
data.info = userDetails
data.sync = 1
do {
try self.userInfoObjectContext.save()
} catch {
fatalError("Failure to save context: \(error)")
}
}
func deleteUserInfoFromDatabase() {
let fetchRequest = NSFetchRequest(entityName: "UserInfo")
if #available(iOS 9.0, *) {
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try DatabaseManager.sharedInstance.persistentStoreCoordinator.executeRequest(deleteRequest, withContext: self.userInfoObjectContext)
do {
try self.userInfoObjectContext.save()
} catch {
let saveError = error as NSError
print(saveError)
}
} catch let error as NSError {
let saveError = error as NSError
print(saveError)
}
} else {
// Fallback on earlier versions
}
}
func fetchUserInfoFromDatabase(){
let request = NSFetchRequest(entityName: "UserInfo")
do {
let results = try self.userInfoObjectContext.executeFetchRequest(request) as? [UserInfo] //Getting crash here
if results!.count > 0 {
}else{
print("0 results or potential error")
}
} catch {
let saveError = error as NSError
print(saveError)
}
}
I am assigning following object class to Transformable attirbute.
class FleetInfoDetails: NSObject {
var fleetId: Int!
var fleetImage: String!
var accessToken: String!
var email: String!
var phone: String!
var password: String!
var name: String!
var teams: Array<AssignedTeamDetails>?
func encodeWithCoder(_aCoder: NSCoder) { }
func initWithCoder(aCode:NSCoder) {
}
init(json: NSDictionary) {
if let fleetId = json["fleet_id"] as? Int {
self.fleetId = fleetId
}
if let fleetImage = json["fleet_image"] as? String {
if fleetImage.isEmpty{
self.fleetImage = nil
}
self.fleetImage = fleetImage
}
if let accessToken = json["access_token"] as? String {
if accessToken.isEmpty{
self.accessToken = nil
}
self.accessToken = accessToken
}
if let email = json["email"] as? String {
if email.isEmpty{
self.email = nil
}
self.email = email
}
if let phone = json["phone"] as? String {
if phone.isEmpty{
self.phone = nil
}
self.phone = phone
}
if let password = json["password"] as? String {
if password.isEmpty{
self.password = nil
}
self.password = password
}
if let name = json["name"] as? String {
if name.isEmpty{
self.name = nil
}
self.name = name
}
if let items = json["teams"] as? NSArray{
if items.count == 0{
teams = [AssignedTeamDetails]()
} else {
teams = [AssignedTeamDetails]()
}
for item in items{
if let team = AssignedTeamDetails(json: item as! NSDictionary) as AssignedTeamDetails! {
teams?.append(team)
}
}
}
}
I just fight and fight and finally achieved it. Here is My solution:
class FleetInfoDetails: NSObject, NSCoding {
var fleetId: Int!
var accessToken: String!
required init(coder aDecoder: NSCoder) {
fleetId = aDecoder.decodeObjectForKey("fleetId") as! Int
accessToken = aDecoder.decodeObjectForKey("accessToken") as! String
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(fleetId, forKey: "fleetId")
aCoder.encodeObject(accessToken, forKey: "accessToken")
}
init(json: NSDictionary) {
if let fleetId = json["fleet_id"] as? Int {
self.fleetId = fleetId
}
if let accessToken = json["access_token"] as? String {
if accessToken.isEmpty{
self.accessToken = nil
}
self.accessToken = accessToken
}
}
}
I just added NSCoding in my object class. And then implemented required init() and encodeWithCode() methods. After that I used NSKeyedArchiver and NSKeyedUnarchiver to save and fetch data.
func saveUserInfoInDatabase(userDetails: FleetInfoDetails) {
self.deleteUserInfoFromDatabase()
let entityDescription = NSEntityDescription.entityForName("UserInfo", inManagedObjectContext: self.userInfoObjectContext)
let data = UserInfo(entity: entityDescription!, insertIntoManagedObjectContext: self.userInfoObjectContext)
data.info = NSKeyedArchiver.archivedDataWithRootObject(userDetails)
data.sync = 1
do {
try self.userInfoObjectContext.save()
} catch {
fatalError("Failure to save context: \(error)")
}
}
func fetchUserInfoFromDatabase(){
let request = NSFetchRequest(entityName: "UserInfo")
do {
let results = try self.userInfoObjectContext.executeFetchRequest(request) as? [UserInfo]
if results!.count > 0 {
let userData = NSData(data: results?.first?.valueForKey("info") as! NSData)
let userDetails = NSKeyedUnarchiver.unarchiveObjectWithData(userData) as! FleetInfoDetails
}else{
print("0 results or potential error")
}
} catch {
let saveError = error as NSError
print(saveError)
}
}
Hope it will help anyone. If there is any other solution please let me know.