Search code examples
iosswiftuitableviewcloudkit

CloudKit-Won't update (Swift)


import UIKit
import CloudKit

class IdeaTableViewController: UITableViewController {

var posts = [CKRecord]()
var refresh:UIRefreshControl!

override func viewDidLoad() {
    super.viewDidLoad()
    refresh = UIRefreshControl()
    refresh.attributedTitle = NSAttributedString(string: "Pull to Refresh")
    refresh.addTarget(self, action: "loadData", forControlEvents: .ValueChanged)
    self.tableView.addSubview(refresh)
    loadData()
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return posts.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)

    if posts.count == 0{
        return cell
        print("zero Posts")
    }
    let post = posts[indexPath.row]

    if let postContent = post["content"] as? String{
        let dateFormat = NSDateFormatter()
        dateFormat.dateFormat = "MM/dd/yyyy"
        let dateString = dateFormat.stringFromDate(post.creationDate!)
        print("trying to Write the Post...")
        cell.textLabel?.text = "\(postContent)"
        cell.detailTextLabel?.text = "\(dateString)"

    }

    return cell
}

func loadData(){
    posts = [CKRecord]()
    let publicData = CKContainer.defaultContainer().publicCloudDatabase
    let query = CKQuery(recordType: "Post", predicate: NSPredicate(format: "TRUEPREDICATE", argumentArray: nil))
    query.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
    publicData.performQuery(query, inZoneWithID: nil) { (results:[CKRecord]?, error:NSError?) -> Void in
        if let posts = results{
            self.posts = posts
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.tableView.reloadData()
                self.refresh.endRefreshing()
            })
        }
    }

}

@IBAction func add(sender: AnyObject) {
    let alert = UIAlertController(title: "New Idea", message: "Tell us what you're thinking.", preferredStyle: .Alert)
    alert.addTextFieldWithConfigurationHandler { (textField: UITextField) -> Void in
        textField.placeholder = "Idea"
    }
    alert.addAction(UIAlertAction(title: "Post", style: .Default, handler: { (action: UIAlertAction) -> Void in

        let textField = alert.textFields!.first!

        if textField.text != ""{

            let newPost = CKRecord(recordType: "Post")
            newPost["content"] = textField.text
            let publicData = CKContainer.defaultContainer().publicCloudDatabase
            publicData.saveRecord(newPost, completionHandler: {(
                record:CKRecord?, error:NSError?) -> Void in
                if error == nil{
                    print("Post Saved")
                    dispatch_async(dispatch_get_main_queue(), {() -> Void in
                        self.tableView.beginUpdates()
                        self.posts.insert(newPost, atIndex: 0)
                        let indexPath = NSIndexPath(forRow: 0, inSection: 0)
                        self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Top)
                        self.tableView.endUpdates()
                    })
                }else{
                    print("Post ERROR")
                    print(ErrorType)
                }
            })

        }

    }))

    alert.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil))

    self.presentViewController(alert, animated: true, completion: nil)
  }


}

When my table should be updating when I post something, it doesn't do anything. I don't know if I just wrote a bad error or something. The posts appear on cloud kit iCloud online but not in my table, even after I refresh it.


Solution

  • Although you're using the CKDatabase.performQuery convenience method, you may be hitting the same situation described by the Warning in CKQueryOperation.recordFetchedBlock:

    Query indexes are updated asynchronously so they are not guaranteed to be current. If you query for records that you recently changed and not allow enough time for those changes to be processed, the query results may be incorrect. The results may not contain the correct records and the records may be out of order.

    Source: CKQueryOperation Class Reference

    A workaround is described in this answer to another question:

    If you're using a CKQuery to back a view you'll want to keep a side table of records that have been modified locally and stitch those into the view until the query starts returning that record.