import UIKit
class FeedTableViewController: UITableViewController {
var navBar:UINavigationBar=UINavigationBar()
let font = UIFont(name: "Baskerville", size: 15)
var feedData:NSMutableArray = NSMutableArray()
required init(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
}
@IBAction func likeButton(sender: AnyObject) {
if var votes:Int? = quote!.objectForKey("votes") as? Int {
votes!++
}
}
@IBAction func loadData(sender: AnyObject?) {
feedData.removeAllObjects()
var findFeedData:PFQuery = PFQuery(className: "userQuotes")
findFeedData.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]?, error:NSError?)->Void in
if error == nil{
if let objs = objects{
for object in objs{
let quote:PFObject = object as! PFObject
self.feedData.addObject(quote)
// let user:PFUser = (object as! NSArray).lastObject as! PFUser
}
//println(self.feedData)
let array:NSArray = self.feedData.reverseObjectEnumerator().allObjects
self.feedData = NSMutableArray(array: array)
NSOperationQueue.mainQueue().addOperationWithBlock({
self.tableView.reloadData()
})
}
}
}
}
override func viewDidAppear(animated: Bool) {
self.loadData( nil )
}
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Quotezilla"
// 3
//self.navigationItem.setRightBarButtonItem(rightSearchBarButtonItem, animated: true)
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return feedData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:QuoteTableViewCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! QuoteTableViewCell
let quote:PFObject = self.feedData.objectAtIndex(indexPath.row) as! PFObject
cell.contentTextView!.font = font
cell.timeStampLabel!.font = font
cell.publisherLabel!.font = font
cell.contentTextView.alpha = 0
cell.timeStampLabel.alpha = 0
cell.publisherLabel.alpha = 0
cell.contentTextView.text = quote.objectForKey("content") as! String
//cell.publisherLabel.text = quote.objectForKey("publisher") as? String
/* func loadLikes(){
if var votes:Int? = quote.objectForKey("votes") as? Int {
votes!++
}
}*/
var dateFormatter:NSDateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "EEEE, MMM d, h:mm a"
cell.timeStampLabel.text = dateFormatter.stringFromDate(quote.createdAt!)
var votes:Int? = quote["votes"] as? Int
if votes == nil {
votes = 0
}
cell.likesLabel?.text = "\(votes!)"
var myObject = quote["publisher"] as? PFObject
myObject?.fetchIfNeeded()
if let foundUser = myObject as? PFUser{
cell.publisherLabel.text = foundUser.username
UIView.animateWithDuration(0.7, animations: {
cell.contentTextView.alpha = 1
cell.timeStampLabel.alpha = 1
cell.publisherLabel.alpha = 1
})
}
return cell
}
So what I am essentially attempting to do is create a likes or votes button. As you see in the code I have a likeButton action that is supposed to auto-increment the likes section in parse. I display the current likes that I have filled into the rows in Parse itself in the cellForRowAtIndexPath
function. The problem is that I cannot call quote.objectForKey("votes")
, because I initialize it later. I have been poring over this problem and cannot find a way to make the votes update in parse through the likeButton action.
You must live with life on the network. That means your table won't have certain data available when the App starts. Handle a missing object or missing key within a particular cell gracefully and just use some kind of placeholder value. When the parse callback executes, you are already correctly forcing a refresh.
OK So BIG EDIT
This class needed a lot of work. I'm not even going to spell out every change here, but it's basically a complete Parse.com tutorial at this point.
This code compiles cleanly but I can't be sure of everything in your context. In particular do you have a 'likesButton' on every table row as part of your custom table cell view? I'm assuming that.
class FeedTableViewController: UITableViewController {
var navBar = UINavigationBar()
let font = UIFont(name: "Baskerville", size: 15)
var feedData = [PFObject]()
static let cellID = "cell"
// NOTE! See how this tag is set below
@IBAction func likeButton(sender: UIButton) {
let quote = feedData[sender.tag]
if let votes = quote.objectForKey("votes") as? Int {
quote.setObject(votes + 1, forKey: "votes")
}
else {
// CHALLENGE FOR YOU: handle the case of no votes attribute
}
// UPDATE the local UI
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: sender.tag, inSection: 0)],
withRowAnimation: .None)
// CHALLENGE FOR YOU: UPDATE Parse...start a new question if necessary
}
@IBAction func loadData(sender: AnyObject?) {
feedData.removeAll()
PFQuery(className: "userQuotes").findObjectsInBackgroundWithBlock {
[unowned self]
(objects: [AnyObject]?, error: NSError?) -> Void in
if let objs = objects {
for object in objs {
self.feedData.append(object as! PFObject)
}
self.feedData = self.feedData.reverse()
}
NSOperationQueue.mainQueue().addOperationWithBlock { self.tableView.reloadData() }
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.loadData(nil)
self.title = "Quotezilla"
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return feedData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(FeedTableViewController.cellID, forIndexPath: indexPath) as! QuoteTableViewCell
cell.likesButton!.tag = indexPath.row // See how tag works with the above
cell.contentTextView!.font = font
cell.timeStampLabel!.font = font
cell.publisherLabel!.font = font
cell.contentTextView.alpha = 0.0
cell.timeStampLabel.alpha = 0.0
cell.publisherLabel.alpha = 0.0
let q = feedData[indexPath.row]
if let content = q.objectForKey("content") as? String {
cell.contentTextView.text = content
}
else {
cell.contentTextView.text = "Content not found!"
}
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "EEEE, MMM d, h:mm a"
cell.timeStampLabel.text = dateFormatter.stringFromDate(q.createdAt!)
let votes = (q.objectForKey("votes") as? Int) ?? 0
cell.likesLabel?.text = "\(votes)"
let myObject = q.objectForKey("publisher") as? PFObject
myObject?.fetchInBackgroundWithBlock {
[unowned self]
(object: PFObject?, error: NSError?) in
NSOperationQueue.mainQueue().addOperationWithBlock {
if let foundUser = object as? PFUser {
cell.publisherLabel.text = foundUser.username
UIView.animateWithDuration(0.7) {
cell.contentTextView.alpha = 1.0
cell.timeStampLabel.alpha = 1.0
cell.publisherLabel.alpha = 1.0
}
}
else {
cell.publisherLabel.text = "Publisher not found!"
}
}
}
return cell
}
}