NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>

Hacking With Swift - Project 38 - Table view going crazy when trying to save/load the newest date with UserDefaults

Forums > Swift

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.

   

Hacking with Swift is sponsored by Fernando Olivares

SPONSORED Would you describe yourself as knowledgeable, but struggling when you have to come up with your own code? Fernando Olivares has a new book containing iOS rules you can immediately apply to your coding habits to see dramatic improvements, while also teaching applied programming fundamentals seen in refactored code from published apps.

Try the book!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.