I am making some good progress on my social networking application. I have run into an issue. I have a ViewController that provides a TableView that is populated with content from my parse database. In the cells I have a RSVP button that is supposed to send a RSVP based on the indexPath to the database when clicked and remove when it is clicked again. I believe my logic is correct, however, I keep receiving the error:
Operation is invalid after previous operation.
I placed a breakpoint to locate the cause of the crash and I have identified that it is happening at the addUniqueObject line within the rsvpButtonClicked IBOutlet function.
Can someone help me? My code is below.
import UIKit
import CoreLocation
class MainFeedViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var eventsTable: UITableView!
var user = PFUser.currentUser()
var refresher: UIRefreshControl!
var eventId = [String]()
var eventNames = [String]()
var eventCity = [String]()
var imageFiles = [PFFile]()
var getEventsQuery = 0
var userRsvps = [NSArray]()
var rsvp = 0
override func viewDidLoad() {
super.viewDidLoad()
getuserlocation()
getTodayDate()
}
override func viewWillAppear(animated: Bool) {
refreshControl()
//getMyRsvps()
}
override func viewDidAppear(animated: Bool) {
let timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: "eventQuery", userInfo: nil, repeats: false)
}
func getMyRsvps() {
var getRsvps = PFUser.query()
getRsvps.whereKey("objectId", equalTo: user.objectId)
getRsvps.whereKeyExists("myrsvp")
getRsvps.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
self.userRsvps.append(objects)
}
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.eventsTable.dequeueReusableCellWithIdentifier("mainFeedContent") as MainFeedContentTableViewCell
cell.eventName.text = eventNames[indexPath.row]
imageFiles[indexPath.row].getDataInBackgroundWithBlock{
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
let image = UIImage(data: imageData)
cell.eventImage.image = image
}
}
cell.rsvpButton.tag = indexPath.row
cell.rsvpButton.addTarget(self, action: "rsvpButtonClick:", forControlEvents: UIControlEvents.TouchUpInside)
return cell
}
#IBAction func rsvpButtonClick(sender: UIButton) {
var senderButton = sender
println("Current row \(senderButton.tag)")
var tempObject = eventId[senderButton.tag]
println("\(tempObject)")
PFUser.currentUser().addUniqueObject(tempObject, forKey: "myrsvp")
PFUser.currentUser().saveInBackground()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return eventId.count
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let mainViewIdentifier = "showDetail"
if segue.identifier == mainViewIdentifier {
if let destination = segue.destinationViewController as? DetailViewController {
if let feedIndex = eventsTable.indexPathForSelectedRow()?.row {
destination.eventNames = eventNames[feedIndex]
destination.eventId = eventId[feedIndex]
destination.eventImagesFile = imageFiles[feedIndex]
}
}
}
}
func eventQuery() {
let getEventsQuery = PFQuery(className: "Events")
getEventsQuery.whereKey("eventLocation", nearGeoPoint: user["location"] as PFGeoPoint, withinMiles: user["preferredDistanceEvents"] as Double)
getEventsQuery.limit = 16
getEventsQuery.findObjectsInBackgroundWithBlock {(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
println("Successfully retrieved \(objects.count) events")
for object in objects {
self.eventId.append(object.objectId)
self.eventNames.append(object["eventName"] as String)
self.eventCity.append(object["eventCity"] as String)
self.imageFiles.append(object["eventPicture"] as PFFile)
self.eventsTable.reloadData()
}
} else {
println(error)
}
}
}
func refreshControl() {
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
self.eventsTable.addSubview(refresher)
}
/*
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
var height: CGFloat = scrollView.frame.size.height
var contentYoffset: CGFloat = scrollView.contentOffset.y
var distanceFromBottom: CGFloat = scrollView.contentSize.height - contentYoffset
if distanceFromBottom <= height {
println("End of Table")
refresh()
}
}
*/
func refresh() {
self.getEventsQuery++
if self.getEventsQuery < self.eventId.count {
let refreshEventsQuery = PFQuery(className: "Events")
refreshEventsQuery.whereKey("location", nearGeoPoint: user["location"] as PFGeoPoint, withinMiles: user["preferredDistanceEvents"] as Double)
refreshEventsQuery.whereKey("objectId", notContainedIn: eventId)
refreshEventsQuery.limit = 4
refreshEventsQuery.findObjectsInBackgroundWithBlock {(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
println("Successfully retrieved \(objects.count) events")
for object in objects {
self.eventNames.append(object["eventName"] as String)
self.eventCity.append(object["City"] as String)
self.imageFiles.append(object["eventPicture"] as PFFile)
self.eventId.append(object.objectId)
self.eventsTable.reloadData()
}
} else {
println(error)
}
}
} else {
println("No More Events. Sorry")
}
self.refresher.endRefreshing()
}
func getuserlocation() {
PFGeoPoint.geoPointForCurrentLocationInBackground { (geopoint: PFGeoPoint!, error: NSError!) -> Void in
if error == nil {
self.user["location"] = geopoint
self.user.saveInBackground()
}
}
}
func getTodayDate(){
var today = NSDate()
var calendar = NSCalendar.currentCalendar()
var flags = NSCalendarUnit.HourCalendarUnit | NSCalendarUnit.MinuteCalendarUnit
var components = calendar.components(flags, fromDate: today)
var hour = components.hour
var minutes = components.minute
println("Today is \(today). The time is \(hour):\(minutes)")
}
}
I think this is a bug in parse (in code shared with JS, because I've experienced the problem there). Specifically, this failure appears when intermixing the add and remove PFObject methods to manipulate array columns.
I've used both of the following workarounds with some success:
Delimit adds and removes with intervening saves. In other words, build your own addToColAndSave and removeFromColAndSave convenience methods. If you've called one of them, don't call the other until the save completes.
Probably easier: restructure the code to avoid the add/remove methods on arrays. Instead, use the getter (get in JS, objectForKey: in iOS) to get the array in memory, then manipulate it natively. Use the sdk setter to update the object.
Related
I have been trying to create a voting system so I can log the votes a certain image gets and display them in a cell.
I can't seem to get my voting to work properly I'm currently trying to use the += and -= operands because I couldn't figure out the increment count, but I keep getting an error message on post.count += or -= 1 of : PFObject does not have a member named count which I do in my parse backend:
Here is my code that i have so far:
import UIKit
import Parse
class HomePage: UITableViewController {
let post = PFObject(className: "Post")
var images = [UIImage]()
var titles = [String]()
var imageFile = [PFFile]()
var count = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
println(PFUser.currentUser())
var query = PFQuery(className:"Post")
query.orderByDescending("createdAt")
query.limit = 15
query.findObjectsInBackgroundWithBlock {(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
println("Successfully retrieved \(objects!.count) scores.")
println(objects!)
if let objects = objects as? [PFObject] {
for object in objects {
if let title = object["Title"] as? String {
self.titles.append(title)
}
if let imgFile = object["imageFile"] as? PFFile {
self.imageFile.append(imgFile)
}
if let voteCounter = object["count"] as? Int {
self.count.append(voteCounter)
}
self.tableView.reloadData()
}
} else {
// Log details of the failure
println(error)
}
}
}
}
/* println("Successfully retrieved \(objects!.count) scores.")
for object in objects! {
self.titles.append(object["Title"] as! String)
self.imageFile.append(object["imageFile"] as! PFFile)
self.tableView.reloadData()
}*/
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titles.count
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 500
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var myCell:cell = self.tableView.dequeueReusableCellWithIdentifier("myCell") as! cell
myCell.rank.text = "21"
myCell.votes.text = "\(count)"
myCell.postDescription.text = titles[indexPath.row]
imageFile[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
myCell.postedImage.image = downloadedImage
}
}
var swipeRight = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
myCell.postedImage.userInteractionEnabled = true;
myCell.postedImage.addGestureRecognizer(swipeRight)
var swipeLeft = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Left
myCell.postedImage.userInteractionEnabled = true;
myCell.postedImage.addGestureRecognizer(swipeLeft)
return myCell
}
func respondToSwipeGesture(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Right:
post.count += 1
println("Swiped right")
case UISwipeGestureRecognizerDirection.Left:
post.count -= 1
println("Swiped Left")
default:
break
}
}
}
}
How can I make the count work in this code? Why do I keep getting that error and how can I log the count for each specific image?
any type of voting system code would be appreciated i can change it up i just want to keep the swipe gesture as the way you upvote and downvote.
Your table has a number of lines (at least four) that don't have any "count" parameters. Delete them, or change your code to do this:
var potentialVoteCounter : Int? = object["count"]
if potentialVoteCounter == nil {
// create "count" in this Parse object
let zero:NSNumber = 0
object["count"] = zero
}
if let voteCounter = object["count"] as? Int {
self.count.append(voteCounter)
}
or
if let voteCounter = object["count"] as? Int {
// do nothing here...
} else {
// create "count" in this object
let zero:NSNumber = 0
object["count"] = zero;
}
if let voteCounter = object["count"] as? Int {
self.count.append(voteCounter)
}
making certain to save your updated Parse object at the end (so the table will reflect changes that you made)
I am trying to set up a voting system Parse as my backend.
I want to use swipe left and right as the voting method and I am using a query.getObjectInBackgroundWithID so that I can update the vote count to my backend.
I am having trouble querying it and also saving the votes in the back and having that append in to the cell so that the vote count will be added on the tableview cells.
Keep on receiving this error in my log for the query:
no results matched the query (Code: 101, Version: 1.7.2)
How can I correct this? Also How can I make the voting system work after I get the query to work and update the backend?
Here is my code so far:
import UIKit
import Parse
class HomePage: UITableViewController {
let post = PFObject(className: "Post")
var images = [UIImage]()
var titles = [String]()
var imageFile = [PFFile]()
var voteCounter = 0
var count = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
println(PFUser.currentUser())
var query = PFQuery(className:"Post")
query.orderByDescending("createdAt")
query.limit = 15
query.findObjectsInBackgroundWithBlock {(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
println("Successfully retrieved \(objects!.count) scores.")
println(objects!)
if let objects = objects as? [PFObject] {
for object in objects {
if let title = object["Title"] as? String {
self.titles.append(title)
}
if let imgFile = object["imageFile"] as? PFFile {
self.imageFile.append(imgFile)
}
if let voteCounter = object["count"] as? Int {
self.count.append(voteCounter)
}
self.tableView.reloadData()
}
} else {
// Log details of the failure
println(error)
}
}
}
}
/* println("Successfully retrieved \(objects!.count) scores.")
for object in objects! {
self.titles.append(object["Title"] as! String)
self.imageFile.append(object["imageFile"] as! PFFile)
self.tableView.reloadData()
}*/
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titles.count
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 500
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var myCell:cell = self.tableView.dequeueReusableCellWithIdentifier("myCell") as! cell
myCell.rank.text = "21"
myCell.votes.text = "\(count)"
myCell.postDescription.text = titles[indexPath.row]
imageFile[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
myCell.postedImage.image = downloadedImage
}
}
var swipeRight = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
myCell.postedImage.userInteractionEnabled = true;
myCell.postedImage.addGestureRecognizer(swipeRight)
var swipeLeft = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Left
myCell.postedImage.userInteractionEnabled = true;
myCell.postedImage.addGestureRecognizer(swipeLeft)
This is the query that I get errors on:
var query = PFQuery(className:"Post")
query.getObjectInBackgroundWithId("count") {
(Post: PFObject?, error: NSError?) -> Void in
if error != nil {
println(error)
} else if let Post = Post {
Post["count"] = self.voteCounter
Post.saveInBackground()
}
}
return myCell
}
func respondToSwipeGesture(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Right:
voteCounter += 1
println("Swiped right")
case UISwipeGestureRecognizerDirection.Left:
voteCounter -= 1
println("Swiped Left")
default:
break
}
}
}
}
Also here is my Parse backend:
ive added the new code now
import UIKit
import Parse
class HomePage: UITableViewController {
let post = PFObject(className: "Post")
var images = [UIImage]()
var titles = [String]()
var imageFile = [PFFile]()
var votingObjects: [PFObject] = []
override func viewDidLoad() {
super.viewDidLoad()
println(PFUser.currentUser())
println(PFUser.currentUser())
var query = PFQuery(className:"Post")
query.orderByDescending("createdAt")
query.limit = 15
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
println("Successfully retrieved \(objects!.count) scores.")
println(objects!)
for objectRaw in objects! {
let object = objectRaw as! PFObject
self.votingObjects.append(object)
// Adding them to the array
if let title = object["Title"] as? String {
self.titles.append(title)
}
if let imgFile = object["imageFile"] as? PFFile {
self.imageFile.append(imgFile)
}
}
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
// Updating the tableView on the main thread - important. Do some research on Grand Central Dispatch :)
})
} else {
println(error)
// Error
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titles.count
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 500
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var myCell:cell = self.tableView.dequeueReusableCellWithIdentifier("myCell") as! cell
myCell.rank.text = "21"
i cant figure out whats the right code here for the myCell.votes.text to =
myCell.votes.text = votingObjects[indexPath.row]["count"] as? String
myCell.postDescription.text = titles[indexPath.row]
imageFile[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
myCell.postedImage.image = downloadedImage
}
}
var swipeRight = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
myCell.postedImage.userInteractionEnabled = true;
myCell.postedImage.addGestureRecognizer(swipeRight)
var swipeLeft = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Left
myCell.postedImage.userInteractionEnabled = true;
myCell.postedImage.addGestureRecognizer(swipeLeft)
return myCell
}
having an issue here:
func respondToSwipeGesture(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Right:
updateVote(true, objectId: String())
println("Swiped right")
case UISwipeGestureRecognizerDirection.Left:
updateVote(false, objectId: String())
println("Swiped Left")
default:
break
}
}
}
func updateVote(increment: Bool, objectId : String) {
// Create a pointer to an object of class Posts with id 'objectId'
var object = PFObject(withoutDataWithClassName: "Post", objectId: objectId)
// Increment the current value of the quantity key by 1
if increment == true {
object.incrementKey("count", byAmount: 1)
} else {
object.incrementKey("count", byAmount: -1)
}
// Save
object.saveInBackgroundWithBlock(nil)
}
}
but i keep recieving the error of cannot update without specific objectId whenever i swipe and initiate the gesture recognizer. i also cant figure out how to display the votes in my cell
It looks like you are querying the Parse db for an objectID which doesn't exist. This is because when you receive the objects, the attribute "count" is the number of votes right... but when you query for an object, you are using "count" as the objectID which obviously won't work. Your idea of using the variable count will also not work.
What I would recommend is a slight adjustment in your structures.
When receiving the objects from the initial query, store them in an array of Parse Objects. This way, you retain all of their information and it will be much easier to update them. The will also provide an attribute object.objectId which is a String, which is what you will need when querying the db again.
Another tip is Parse supports an increment function when dealing with a column of type number
Also, when working on background threads, you should make any UI calls on the main thread using GCD.
Code:
Initial query -
var votingObjects: [PFObject] = []
override func viewDidLoad() {
super.viewDidLoad()
println(PFUser.currentUser())
var query = PFQuery(className:"Post")
query.orderByDescending("createdAt")
query.limit = 15
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
println("Successfully retrieved \(objects!.count) scores.")
println(objects!)
for objectRaw in objects {
let object = objectRaw as! PFObject
self.votingObjects.append(object) // Adding them to the array
}
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData() // Updating the tableView on the main thread - important. Do some research on Grand Central Dispatch :)
})
} else {
// Error
}
}
}
// Pass true if you want to upvote or false if downvote
func updateVote(increment: Bool, objectId : String) {
// Create a pointer to an object of class Posts with id 'objectId'
var object = PFObject(withoutDataWithClassName: "Posts", objectId: objectId)
// Increment the current value of the quantity key by 1
if increment == true {
object.incrementKey("count", byAmount: 1)
} else {
object.incrementKey("count", byAmount: -1)
}
// Save
object.saveInBackgroundWithBlock(nil)
}
}
Your tableView functions will all link to the array now..
numberOfRows will simply use votingObjects.count
TitleForRow will use votingObject[indexPath.row]["Title"]! // Should be 'title'
And any time you want to refer to a voting objects ID, you simply use votingObject[index].objectId
Hope I didn't miss anything :)
I am trying to create a voting system and store it to my backend and have it come up for each individual picture and be stored for each picture. I created a column in my backend Parse called "count" but i cant seem to get the votes to be brought up or saved in the back and added. I am using a swipeGestureRecognizer to initiate the voting right for one up left for one down but i cant get the correct syntax at the switch statement for the -= and += and i get the error of Binary operator '+='/'-=' cannot be applied to operands of type '[(Int)]' and 'Int'what can i do to make the voting system work to both save in the backend and be brought up and shown each individual pics votes?
import UIKit
import Parse
class HomePage: UITableViewController {
var images = [UIImage]()
var titles = [String]()
var imageFile = [PFFile]()
var count = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
println(PFUser.currentUser())
var query = PFQuery(className:"Post")
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock {(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
println("Successfully retrieved \(objects!.count) scores.")
println(objects!)
for object in objects! {
if let title = object["Title"] as? String {
self.titles.append(title)
}
if let imgFile = object["imageFile"] as? PFFile {
self.imageFile.append(imgFile)
}
if let voteCounter = object["count"] as? Int {
self.count.append(voteCounter)
}
self.tableView.reloadData()
}
} else {
// Log details of the failure
println(error)
}
}
}
/* println("Successfully retrieved \(objects!.count) scores.")
for object in objects! {
self.titles.append(object["Title"] as! String)
self.imageFile.append(object["imageFile"] as! PFFile)
self.tableView.reloadData()
}*/
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titles.count
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 500
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var myCell:cell = self.tableView.dequeueReusableCellWithIdentifier("myCell") as! cell
myCell.rank.text = "21"
myCell.votes.text = "\(count)"
myCell.postDescription.text = titles[indexPath.row]
imageFile[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
myCell.postedImage.image = downloadedImage
}
}
var swipeRight = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
myCell.postedImage.userInteractionEnabled = true;
myCell.postedImage.addGestureRecognizer(swipeRight)
var swipeLeft = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Left
myCell.postedImage.userInteractionEnabled = true;
myCell.postedImage.addGestureRecognizer(swipeLeft)
return myCell
}
func respondToSwipeGesture(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Right:
count += 1
println("Swiped right")
case UISwipeGestureRecognizerDirection.Left:
count -= 1
println("Swiped Left")
default:
break
}
}
}
}
this is what i have now but the voting still wont get logged into parse and the post.count += 1 and post.count-=1 is receiving error messages of 'PFObject' does not have a member named 'count' where am i going wrong?
First of all, what you display on screen should depend entirely on your Parse model. What I mean is - you increment a count property every time a user votes. What will happen if the user stays in this screen for an hour and by that time 10 more users also vote? This won't be updated in the current screen and the user will see votes that are not up to date.
So what you can do is to create an object which inherits from PFObject. This object will be tied to Parse and will be always up to date.
What you can start with is reading the documentation. This can help you too.
So the main idea is to have your Parse columns as properties of a PFObject subclass:
class Post: PFObject, PFSubclassing {
#NSManaged var count: Int
class func parseClassName() -> String! {
return "Post"
}
}
In your AppDelegate's application(_:didFinishLaunchingWithOptions:) method register your Parse class like this:
Post.registerSubclass()
When you want to change the count property you'll have to set it and then update the screen:
let post = PFObject(className: "Post")
//increment like this
post.count += 1
//decrement like this
post.count -= 1
//refresh screen
//call reloadData()
Hi I am trying to figure out how to make it so that all my data for my timeline can reload on its own. Here is my current code for the whole TimeLineViewController
import UIKit
import CoreData
class TimelineTableViewController: UITableViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITextFieldDelegate, UIAlertViewDelegate {
var timelineData:NSMutableArray! = NSMutableArray()
override init(style: UITableViewStyle) {
super.init(style: style)
// Custom initialization
}
#IBAction func reportButton(sender: AnyObject) {
performSegueWithIdentifier("reportSegue", sender: self)
}
#IBAction func composeStatus(sender: AnyObject) {
performSegueWithIdentifier("composeSegue", sender:self)
}
#IBAction func logout(sender: AnyObject) {
PFUser.logOut()
var currentUser = PFUser.currentUser() // this will now be nil
performSegueWithIdentifier("logoutSegue", sender:self)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func loadData(){
timelineData.removeAllObjects()
var findTimelineData:PFQuery = PFQuery(className: "woofs")
findTimelineData.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]!, error:NSError!)->Void in
if error == nil{
for object in objects{
let woofs:PFObject = object as PFObject
self.timelineData.addObject(woofs)
}
let array:NSArray = self.timelineData.reverseObjectEnumerator().allObjects
self.timelineData = NSMutableArray(array: array)
self.tableView.reloadData()
}
}
}
override func viewDidAppear(animated: Bool) {
self.loadData()
}
func refresh(sender:AnyObject)
{
// Updating your data here...
self.tableView.reloadData()
self.refreshControl?.endRefreshing()
}
override func viewDidLoad() {
super.viewDidLoad()
var statusBarHidden: Bool
/*var newFeatureAlert:UIAlertController = UIAlertController(title: "Attention", message: "New feature added. You can now Report content that you find offensive. Just tap on Report to get the instructions on how to.", preferredStyle: UIAlertControllerStyle.Alert)
newFeatureAlert.addAction(UIAlertAction(title: "AWESOME!", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(newFeatureAlert, animated: true, completion: nil)*/
self.refreshControl?.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
UITextView.appearance().tintColor = UIColor.blackColor().colorWithAlphaComponent(1.0)
UITextView.appearance().backgroundColor = UIColor.clearColor().colorWithAlphaComponent(0.4)
self.tableView.backgroundView = UIImageView(image: UIImage(named: "hdwallpaper"))
}
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 timelineData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:PAHTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as PAHTableViewCell
cell.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.3)
let woofers:PFObject = self.timelineData.objectAtIndex(indexPath.row) as PFObject
cell.pahTextView.alpha = 0
cell.timestampLabel.alpha = 0
cell.usernameLabel.alpha = 0
cell.pahTextView.text = woofers.objectForKey("content") as String
var dataFormatter:NSDateFormatter = NSDateFormatter()
dataFormatter.dateFormat = "dd-MM-yyyy HH:mm"
cell.timestampLabel.text = dataFormatter.stringFromDate(woofers.createdAt)
var findwoofers:PFQuery = PFUser.query()
findwoofers.whereKey("objectId", equalTo: woofers.objectForKey("woofers").objectId)
findwoofers.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]!, error:NSError!)->Void in if error == nil{
if let user:PFUser = (objects as NSArray).lastObject as? PFUser{
cell.usernameLabel.text = user.username
cell.timestampLabel.alpha = 0
cell.profileImageView.alpha = 0
cell.pahTextView.alpha = 0
if let profileImage = user["profileImage"] as? PFFile{
profileImage.getDataInBackgroundWithBlock {
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
let image = UIImage(data:imageData)
cell.profileImageView.image = image
}else{
let image = UIImage(named: "BLUEPAW")
}
}
}
}
}
UIView.animateWithDuration(1.0, animations:{
cell.profileImageView.alpha = 1
cell.usernameLabel.alpha = 2
cell.timestampLabel.alpha = 4
cell.pahTextView.alpha = 3
})
}
return cell
}
let me know what I need to change to make this work. Thank You.
i trie to find parse users via UISearchBar and display results in a table view.
When i heat search, nothing happened...
My idea was to use the searchText.text as a query to PFUser.
Should i try to use searchBar with search display controller instead ?
Any idea ?
import UIKit
class AllFriendsTableViewController: UITableViewController, UISearchBarDelegate, UISearchDisplayDelegate {
#IBOutlet var SearchDisplay: UISearchDisplayController!
var userList:NSMutableArray = NSMutableArray()
func searchBarShouldBeginEditing(searchBar: UISearchBar!) -> Bool {
return true
}
func searchBarShouldEndEditing(searchBar: UISearchBar!) -> Bool {
return true
}
func searchBar(searchBar: UISearchBar!, textDidChange searchText: String!) {
loadUser()
}
#IBOutlet var searchText: UISearchBar!
func loadUser () {
userList.removeAllObjects()
var findUser:PFQuery = PFUser.query()
findUser.whereKey("username", equalTo: searchText.text)
findUser.findObjectsInBackgroundWithBlock { (objects:[AnyObject]!, error:NSError!) -> Void in
if !(error != nil) {
// The find succeeded.
println("succesfull load Users")
// Do something with the found objects
for object in objects {
self.userList.addObject(object)
println("users added to userlist")
}
self.tableView.reloadData()
} else {
// Log details of the failure
println("error loadind user ")
println("error")
}
}
}
override func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
return 1
}
override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
if tableView == searchDisplayController.searchResultsTableView {
return userList.count
}
else {
return 0
}
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell: AllFirendsTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)as AllFirendsTableViewCell
let users:PFObject = self.userList.objectAtIndex(indexPath!.row) as PFObject
var findUserName:PFQuery = PFUser.query()
findUserName.whereKey("username", containsString: searchText.text)
findUserName.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]!, error:NSError!) -> Void in
if !(error != nil) {
if let user:PFUser = users as? PFUser {
cell.userNameTextField.text = user.username
println("user exist")
// define avatar poster
if let avatarImage:PFFile = user["profileImage"] as? PFFile {
avatarImage.getDataInBackgroundWithBlock{(imageData:NSData!, error:NSError!)-> Void in
if !(error != nil) {
let image:UIImage = UIImage(data: imageData)
cell.avatarImage.image = image as UIImage
cell.avatarImage.layer.cornerRadius = 24
cell.avatarImage.clipsToBounds = true
}
}
}
else {
cell.avatarImage.image = UIImage(named: "Avatar-1")
cell.avatarImage.layer.cornerRadius = 24
cell.avatarImage.clipsToBounds = true
}
}
}
}
return cell
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
navigationController.navigationBar.hidden = false
loadUser()
}
override func viewDidAppear(animated: Bool) {
}
override func viewDidLoad() {
// Do any additional setup after loading the view, typically from a nib.
}
}
I suspect this might be due to you attempting to reload the tableview from the background thread that your network request occurs on. UI updates should happen from the main thread.
In your loadUser() function try doing your tableview reload from the main thread, as follows:
NSOperationQueue.mainQueue().addOperationWithBlock({
self.tableView.reloadData()
})
That may fix your issue.