Reputation: 71
I'm a Swift newbie, building a Core Data app. I've built and run a sample app from Ray Wenderlich's site which works as expected.
I've lifted and modified the following excerpt from Ray's app:
var people: [NSManagedObject] = []
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//1
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
// 2
let fetchrequest = NSFetchRequest<NSManagedObject>(entityName: "Person")
// 3
do {
people = try managedContext.fetch(fetchrequest)
print("\(people.count) fetched from Person")
}
catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
This works as expected. However, the following is what I've implemented in my app:
var players: [NSManagedObject] = []
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Golfer")
do {
players = try managedContext.fetch(fetchRequest)
print("\(players.count) fetched from Golfer")
// Load any saved players, otherwise load sample data.
if players.count == 0 {
// Load the sample data.
// There are no players to load
os_log("Loading sample players", log: OSLog.default, type: .debug)
loadSamplePlayers()
}
}
catch let error as NSError {
print("Could not fetch Golfers. \(error), \(error.userInfo)")
}
}
The sample code always returns the full results of the Person table and the person array count is always equal to the number of rows in the table.
However, for my version, it always reports that the players array has a count of zero. Consequently, the loadSamplePlayers() method is called each time (which adds three sample records into the Golfer table).
Using an SQL Lite database inspector, I can see that the Golfer table continues to grow after each invocation of the app.
I'm stumped on why these two, near-identical, code samples should behave differently.
Any insights would be much appreciated.
Thanks!
EDIT:
Here's the loadSamplePlayers() method and printDatabaseStats() which is also referenced:
private func loadSamplePlayers() {
let sampleFirstNames: [String] = ["Casper", "Jocelyn", "Arthur"]
let sampleLastNames: [String] = ["Vitturio", "Brown", "Mullard"]
let sampleEmails: [String] = ["[email protected]", "[email protected]", "[email protected]"]
let sampleHandicaps: [Double] = [16.2, 6.4, 27.2]
let entity = NSEntityDescription.entity(forEntityName: "Golfer", in: managedObjectContext!)!
for i in 1...3 {
let player = NSManagedObject(entity: entity, insertInto: managedObjectContext)
player.setValue(sampleFirstNames[i-1], forKeyPath: "firstName")
player.setValue(sampleLastNames[i-1], forKey: "lastName")
player.setValue(sampleEmails[i-1], forKey: "emailAddress")
player.setValue(sampleHandicaps[i-1], forKey: "exactHandicap")
// player.setValue(sampleMugshots[i-1], forKey: "mugShot")
print("Prepare to save")
do {
try managedObjectContext?.save()
players.append(player)
}
catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
print("There are now \(printDatabaseStats()) in the Golfers table")
}
}
private func printDatabaseStats() -> Int {
var count = 0
managedObjectContext?.performAndWait {
if let golferCount = try? self.managedObjectContext!.count(for: NSFetchRequest(entityName: "Golfer")) {
print("\(golferCount) Payers")
count = golferCount
}
}
return count
}
This appears to work successfully as the print(...) methods produce the expected console messages and the Golfer table is populated and contains the rows as defined.
Upvotes: 2
Views: 1869
Reputation: 71
Not included in the original question was a class definition, thus:
var managedObjectContext: NSManagedObjectContext? = (UIApplication.shared.delegate as? AppDelegate)?.managedObjectContext
This is defined differently to:
let managedContext = appDelegate.persistentContainer.viewContext
yet I was using them as if they were the same. I normalised the two so they are identical and the problem has gone.
Upvotes: 1