Hi guys,
One of the tasks from Project 38 is:
"Rewrite the getNewestCommitDate() method so that it uses UserDefaults rather than a fetch request in order to fix the bug in the current implementation. (Didn't spot the bug? If users delete the most recent commit message, we also lose our most recent date!)"
So far, getNewestCommitDate()
looked like that:
let formatter = ISO8601DateFormatter()
let newest = Commit.createFetchRequest()
let sort = NSSortDescriptor(key: "date", ascending: false)
newest.sortDescriptors = [sort]
newest.fetchLimit = 1
if let commits = try? container.viewContext.fetch(newest) {
if commits.count > 0 {
return formatter.string(from: commits[0].date.addingTimeInterval(1))
}
}
return formatter.string(from: Date(timeIntervalSince1970: 0)) // if no valid date is found, the method returns a date from the 1st of January 1970, which will reproduce the same behavior we had before introducing this date change.
I changed it to:
func getNewestCommitDate() -> String {
let defaults = UserDefaults.standard
let formatter = ISO8601DateFormatter()
if let newestDate = defaults.string(forKey: "NewestDate") {
print("Newest date loaded: \(newestDate)")
return newestDate
}
return formatter.string(from: Date(timeIntervalSince1970: 0))
}
Saving the newest date occurs here:
func saveNewestCommitDate() {
let defaults = UserDefaults.standard
let formatter = ISO8601DateFormatter()
let string = formatter.string(from: newCommits[0].date)
defaults.setValue(string, forKey: "NewestDate")
print("Newest date saved: \(string)")
}
So, when fetching the data, first we load the newest commit date, and if there is any new one, we save it as the newest:
@objc func fetchCommits() {
let newestCommitDate = getNewestCommitDate()
if let data = try? String(contentsOf: URL(string: "https://api.github.com/repos/apple/swift/commits?per_page=100&since=\(newestCommitDate)")!) {
// give the data to SwiftyJSON to parse:
let jsonCommits = JSON(parseJSON: data)
// read the commits back out as an array:
let jsonCommitArray = jsonCommits.arrayValue
DispatchQueue.main.async { [unowned self] in
for jsonCommit in jsonCommitArray {
let commit = Commit(context: self.container.viewContext)
self.configure(commit: commit, usingJSON: jsonCommit)
self.newCommits.append(commit) // adding the newest commits to an array:
}
self.saveNewestCommitDate()
self.saveContext()
self.loadSavedData()
}
}
}
But if I use what I described above, I ALWAYS get the same error, no matter what I try to do. It's worth to note that I get this error every time I launch the app for THE SECOND TIME. The first launch with the resetted simulator is always successful, with the newest date being saved properly. The error is:
"Thread 1: Exception: "Invalid update: invalid number of rows in section 7. The number of rows contained in an existing section after the update (52) must be equal to the number of rows contained in that section before the update (52), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).""
I noticed that there is always this thing - (0 inserted, 1 deleted) - but I haven't deleted anything from any section, nor have I attempted to do so. What gives? I tried to google the solution but haven't found any situation similar to mine.