Cannot save array into entity (Core Data) - swift

I am trying to save an array of objects into an entity's "to many" relationship of another entity (Not certain how to explain that). I swear this code was working before, but it stopped all of a sudden and I am uncertain as to why as I have not changed any code that has to do with this that I can remember. I receive a SIGABRT error that is " terminating with uncaught exception of type NSException" Any input would be helpful.
func save (completion: (_ finished: Bool) -> ()){
guard let managedContext = appDelegate?.persistentContainer.viewContext else { return }
let workout = Workout(context: managedContext)
workout.nameOfWorkout = workoutNameLabel.text!
workout.exercises = NSSet(array: exercises) // problem exists on this line
workout.numberOfExercises = Int32(exercises.count)
print("\(workout.exercises!.count)")
print ("\(workout.exercises!)")
do{
try managedContext.save()
completion(true)
} catch {
debugPrint("error: \(error.localizedDescription)")
completion(false)
}
}

Related

Could not save data in CoreData swift

I am trying to save data in CoreData. When the app is running everything is ok. I receive info that data is saved and receive messages that it is fetching correct. But when I close the app data just disappeared somewhere.
When I created the project I do not check Core Data, so I added xcdatamodel, import CoreData everywhere, updated AppDelegate with the correct NSPersistentContainer name (the name is name of my xcdatamodel) also in Project-General-Frameworks added CoreData.framework.
Here is part of saving, fetching, and deleting data. The file is separate from VC. I do not receive any type of errors.
In my VC I just call savedata(), to save the data. It works before the app is closed.
import UIKit
import CoreData
var cgsTeams = [TeamsCoreData]()
func savedata() {
saveTeams { (complete) in
if complete {print("TeamsSaved")}
}
}
func saveTeams(completion: (_ finished: Bool) -> ()) {
guard let managedContext = appDelegate?.persistentContainer.viewContext else {return}
let privateManagedContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
privateManagedContext.parent = managedContext
for team in teams {
let teamsCoreData = TeamsCoreData(context: privateManagedContext)
teamsCoreData.team = team.name
teamsCoreData.score = Int32(team.score)
teamsCoreData.number = Int32(team.number)
do{
try privateManagedContext.save()
debugPrint("Succesfully saved teamsCoreData")
completion(true)
} catch{
debugPrint("Could not save - \(error)")
completion(false)
}
}
}
func fetchTeams(completion: (_ complete: Bool) -> ()) {
guard let managedContext = appDelegate?.persistentContainer.viewContext else { return }
let fetchRequest = NSFetchRequest<TeamsCoreData>(entityName: "TeamsCoreData")
do {
cgsTeams = try managedContext.fetch(fetchRequest)
print("cgsGameRules fetched")
teams = [team]()
for cgsTeam in cgsTeams {
print("team - \(cgsTeam.team!) added")
teams.append(team(name:cgsTeam.team!, number: Int(cgsTeam.number), score: Int(cgsTeam.score)))
}
if cgsTeams.count > 1{completion(true)} else {completion (false); print("No teams")}
} catch {
debugPrint("Could not fetch: \(error.localizedDescription)")
completion(false)
}
}
func deleteTeams(){
guard let managedContext = appDelegate?.persistentContainer.viewContext else { return }
let fetchRequest = NSFetchRequest<TeamsCoreData>(entityName: "TeamsCoreData")
let objects = try! managedContext.fetch(fetchRequest)
for obj in objects {
managedContext.delete(obj)
}
do {
try managedContext.save()
} catch {
print("error on delete Team")
}
}
When you save changes in Core Data, the context saves only to its parent context. If it doesn't have a parent context, it saves changes to the persistent store file. You're saving changes on privateManagedObjectContext, which is a child context of viewContext. But you're never saving changes on viewContext. So your child context is telling the parent context about the changes, but the parent never saves those changes anywhere.
You need to either (a) save changes on viewContext, or (b) make privateManagedObjectContext its own stand-alone context, not a child context.

Old Core Data Sync in to CloudKit "iCloud"

I have an app that uses Core Data but now I'm adding CloudKit to my app and I'm having issues on synchronising all the old Core Data.
Does anyone have the same issue? Does anyone have any idea how to synchronise old Core Data?
func fetch(completion: (_ comple: Bool) -> ()) {
guard let managedContext = appDelegate?.persistentContainer.viewContext else { return }
let fetchRequest = NSFetchRequest<Goal>(entityName: "Goal")
do {
goalPasswords = try managedContext.fetch(fetchRequest)
completion(true)
} catch {
debugPrint("Fetch Error \(error.localizedDescription)")
completion(false)
}
}

do - try - catch code doesnt try or catch. just do's

thanks for any help upfront.
url session works perfect with connection, it prints the error as nil. but without it it prints the .localizedDescription just fine and shows me the right error, but then continues to do the do{ try } and crashes with this error in the try line:
Thread 6: Fatal error: Unexpectedly found nil while unwrapping an
Optional value
now I am not even sure if this has anything to do with the errorhandling. thanks for any help with understanding whats going on or just solving the problem!
func getData(completion: (() -> ())?) {
let urlString = URL(string: "https://api.coinmarketcap.com/v1/ticker/")
URLSession.shared.dataTask(with: urlString!, completionHandler: { (data, response , error) in
print("before entering do-try-catch", error?.localizedDescription)
do {
//create Dictionary
print("downloading content")
self.coinData = try JSONSerialization.jsonObject(with: data!) as! [[String:Any]]
//set connection status
self.connection = true
//update tableView
DispatchQueue.main.async {
completion?()
}
} catch {
print("catch", error.localizedDescription)
//set connection status
self.connection = false
//update tableView
DispatchQueue.main.async {
completion?()
}
}
}).resume()
}
Thread 6: Fatal error: Unexpectedly found nil while unwrapping an Optional value is a common problem for beginners.
You try to work with data that is not there.
So for example in your code you force to execute try JSONSerialization.jsonObject(with: data!)
When data is nil the code will crash.
The same at the beginning URLSession.shared.dataTask(with: urlString!, completionHandler: { (data, response, error) {}
When urlString is not a valid URL the code will be crash. (In this case the url seems to be valid).
For more information have a look here:
https://stackoverflow.com/a/24034551/4420355
Try the following snipped it should work
if let data = data {
self.coinData = try JSONSerialization.jsonObject(with: data) as? [[String:Any]]
//... work with coinData
}
Reason why it is crashing is because data is Optional and it should be nil or has some value. On line
self.coinData = try JSONSerialization.jsonObject(with: data!) as! [[String:Any]]
Compiler thinks:
Let's take a look and unwrap this Optianal variable. But it's nil, there is "nothing"! So what should I unwrap? Let's crash and throw Fatal Error message.
How to easily avoid this with Optional binding:
if let data = data {
....do something with data
} else {
...print error message
}
For more information take look at this brilliant answer.
https://stackoverflow.com/a/32170457/3046686

Swift realm return zero objects

I have opened my realm database in Realm browser, i can see that there is are actual data (10 entities).
But when i call print("realm objects \(self.realm.objects(CharacterModel.self))")
Result is empty:
realm objects Results<CharacterModel> <0x7f8d8f204a30> (
)
When i put breakpoint and check data base state at this moment data exist. Why is that happening?
realm is declared like that:
static func realm() -> Realm{
do {
let realm = try Realm()
return realm
} catch let error as NSError {
fatalError("Error opening realm: \(error)")
}
}
The answer may reveal itself if we eliminate some variables:
The following code works with a Realm that contains Person() objects
func doPrintData() {
do {
let realm = try Realm()
print("realm objects \(realm.objects(Person.self))")
} catch let error as NSError {
print(error.localizedDescription)
}
}
the following also works
func realm() -> Realm{
do {
let realm = try Realm()
return realm
} catch let error as NSError {
fatalError("Error opening realm: \(error)")
}
}
func doPrintData() {
do {
let realm = self.realm()
print("realm objects \(realm.objects(Person.self))")
} catch let error as NSError {
print(error.localizedDescription)
}
}
There's probably more code involved but try one of the above solutions and see if it makes a difference.

Fetch request in Swift 2.1.1

I'm trying to convert my Swift 1 code into Swift 2.1.1 code.
So I am trying to add a fetchRequest.
In Swift 1 I did this:
if let results = context.executeFetchRequest(fetchRequest, error:&error),
let managedObject = results.first as? NSManagedObject {
context.deleteObject(managedObject)
}
let saveError: NSError?
context.save(nil)
and
var error: NSError?
let fetchedResults = managedContext.executeFetchRequest(fetchRequest) as! [NSManagedObject]?
if let results = fetchedResults {
people = results
}
else {
print("Could not fetch \(error), \(error!.userInfo)")
}
Swift 2.1 (2nd request -> doesn't work):
do {
let fetchedResults = try managedContext.executeFetchRequest(fetchRequest) as! [NSManagedObject]
// success if it gets here
if let results = fetchedResults {
people = results
}
} catch let error as NSError {
// failed so print error
print("Error: \(error.localizedDescription)")
}
Errors in line (if let results... & let fetchedResults...):
Initializer for conditional binding must have Optional type, not '[AnyObject]'
Call can throw, but is not marked with 'try' and the error is not handled
Errors in line (let fetchedResults...):
Call can throw, but is not marked with 'try' and the error is not handled
Cannot downcast from '[AnyObject]' to a more optional type '[NSManagedObject]?'
Could you please help me to translate this into Swift 2.1.1?
Thanks for your help!
You can wrap it in a do catch block. It will print an error if the let results line fails.
do {
let results = try context.executeFetchRequest(fetchRequest)
// success if it gets here
if let managedObject = results.first as? NSManagedObject {
context.deleteObject(managedObject)
}
} catch let error as NSError {
// failed so print error
print("Error: \(error.localizedDescription)")
}
EDIT
Second request:
do {
let fetchedResults = try managedContext.executeFetchRequest(fetchRequest)
// success if it gets here
if let results = fetchedResults as? [NSManagedObject]{
people = results
}
} catch let error as NSError {
// failed so print error
print("Error: \(error.localizedDescription)")
}