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.
Related
I'm Stuck on this issue and I have tried different 'fixes' for this issue however nothing seems to work. Code for Ref:
class FindAParty:UITableViewController{
var partyData:NSMutableArray! = NSMutableArray()
//var user:NSMutableArray = NSMutableArray()
override init(style: UITableViewStyle){
super.init(style: style)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
//fatalError("init(coder:) has not been implemented")
}
#IBAction func loadData(){
print ("Load Data went through")
partyData.removeAllObjects()
print ("Remove ALL Objeccts")
let findPartyData:PFQuery = PFQuery(className: "Party")
print("PFQuery...")
findPartyData.findObjectsInBackground{
(objects:[PFObject]?, error:Error?)->Void in
if error != nil {
print("Error")
}else{
for object in objects!{
let party:PFObject = object as PFObject
self.partyData.add("party")
}
let array:NSArray = self.partyData.reverseObjectEnumerator().allObjects as NSArray
self.partyData = NSMutableArray(array: array)
self.tableView.reloadData()
}
}
}
override func viewDidAppear(_ animated: Bool) {
self.loadData()
print("View Did Appear")
}
override func viewDidLoad() {
super.viewDidLoad()
print("ViewDidLoad")
//self.loadData()
// 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.
}
// #pragma mark - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return partyData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! FindAPartyCell
//Error Happens Below
let party:PFObject = self.partyData.object(at: indexPath.row) as! PFObject
cell.typeOfPartyLabel.alpha = 0
cell.timeOfPartyLabel.alpha = 0
cell.usernameLabel.alpha = 0
cell.typeOfPartyLabel.text = party.object(forKey: "partyTitle") as? String
cell.timeOfPartyLabel.text = party.object(forKey: "partyTime") as? String
cell.usernameLabel.text = party.object(forKey: "Username") as? String
// var dataFormatter:NSDateFormatter = NSDateFormatter()
//dataFormatter.dateFormat = "yyyy-MM-dd HH:mm"
//cell.timestampLabel.text = dataFormatter.stringFromDate(sweet.createdAt)
let findUser:PFQuery = PFUser.query()!
findUser.whereKey("objectId", equalTo: party.object(forKey: "Username")!)
findUser.findObjectsInBackground {
(objects:[PFObject]?, error: Error?) -> Void in // Changes NSError to Error
if error == nil{
let user:PFUser = (objects)!.last as! PFUser
cell.usernameLabel.text = user.username
UIView.animate(withDuration: 0.5, animations: {
cell.typeOfPartyLabel.alpha = 1
cell.timeOfPartyLabel.alpha = 1
cell.usernameLabel.alpha = 1
})
}
}
return cell
}}
Someone recommended changing : let party:PFObject = self.partyData.object(at: indexPath.row) as! PFObject
to :
let party = self.partyData.object(at: indexPath!.row)
However this did not fix it and I am at a loss to how I should fix it the app build successfully and every other aspect of it runs however this is the only part that fails. I am using Parse and Amazon as my backend.
Declare the data source array
var partyData = [PFObject]()
and change loadData() to
#IBAction func loadData(){
print ("Load Data went through")
partyData.removeAll()
print ("Remove ALL Objeccts")
let findPartyData = PFQuery(className: "Party")
print("PFQuery...")
findPartyData.findObjectsInBackground {
(objects:[PFObject]?, error:Error?)->Void in
if error != nil {
print(error!)
} else{
if let objects = objects {
self.partyData = objects.reversed()
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
}
and get a row:
let party = self.partyData[indexPath.row]
Finally replace in cellForRowAt
if error == nil {
let user:PFUser = (objects)!.last as! PFUser
with
if users = objects as? [PFUser], !users.isEmpty {
let user = users.last!
I'm trying to create a query sort of like Yik Yak where I can see a query of messages within a certain location but the results are not displaying the data in the query whenever I post a message. I basically want the message I send to be shown in the query. I think I did my logic correctly in the code but I'm missing something here that could show the data in the query. I've been working on this problem for the last week and just this one fix could end this segment of my project. Can anyone help me with this?
import UIKit
import ParseUI
import Parse
import CoreLocation
#available(iOS 8.0, *)
class HomeViewController: PFQueryTableViewController,CLLocationManagerDelegate {
var messages = [String]()
var users = [String: String]()
let bubbleFeeds = [
("1"),
("2"),
("I3"),
("4"),
("5"),
("6") ]
let locationManager = CLLocationManager()
var currLocation : CLLocationCoordinate2D?
override init(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.parseClassName = "BubbleTest"
self.textKey = "textField"
self.pullToRefreshEnabled = true
self.objectsPerPage = 200
}
private func alert(message : String) {
let alert = UIAlertController(title: "Oops something went wrong.", message: message, preferredStyle: UIAlertControllerStyle.Alert)
let action = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)
let cancel = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)
let settings = UIAlertAction(title: "Settings", style: UIAlertActionStyle.Default) { (action) -> Void in
UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!)
return
}
alert.addAction(settings)
alert.addAction(action)
self.presentViewController(alert, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 60
self.tableView.rowHeight = UITableViewAutomaticDimension
locationManager.desiredAccuracy = 1000
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
// 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()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
alert("Cannot fetch your location")
}
func queryForTable() -> PFQuery! {
let query = PFQuery(className: "BubbleTest")
if let queryLoc = currLocation {
query.whereKey("location", nearGeoPoint: PFGeoPoint(latitude: queryLoc.latitude, longitude: queryLoc.longitude), withinMiles: 10)
query.limit = 200;
query.orderByDescending("createdAt")
} else {
/* Decide on how the application should react if there is no location available */
query.whereKey("location", nearGeoPoint: PFGeoPoint(latitude: 37.411822, longitude: -121.941125), withinMiles: 10)
query.limit = 200;
query.orderByDescending("createdAt")
}
return query
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
locationManager.stopUpdatingLocation()
if(locations.count > 0){
let location = locations[0]
print(location.coordinate)
currLocation = location.coordinate
} else {
alert("Cannot receive your location")
}
}
override func objectAtIndexPath(indexPath: NSIndexPath!) -> PFObject! {
var obj : PFObject? = nil
if(indexPath.row < self.objects!.count){
obj = self.objects![indexPath.row] as! PFObject
}
return obj
}
// override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//
//
// 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 users.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("object", forIndexPath: indexPath) as! Bubbles
let object = PFObject(className: "BubbleTest")
cell.name.text = object.valueForKey ("userName") as? String
cell.message.text = object.valueForKey("textField") as? String
cell.dateTime.text = "\((indexPath.row + 1) * 3)m ago"
cell.message.numberOfLines = 0
let score = object.valueForKey("count") as! Int
cell.likeCount.text = "\(score)"
let replycnt = object.valueForKey("replies") as! Int
cell.responseCount.text = "\(replycnt) replies"
//cell.userImage.image = PFUser.currentUser()?.valueForKey("photo") as! PFFile
// Configure the cell...
return cell
}
#IBAction func likeButton(sender: AnyObject) {
let hitPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
let hitIndex = self.tableView.indexPathForRowAtPoint(hitPoint)
let object = objectAtIndexPath(hitIndex)
object.incrementKey("count")
object.saveInBackground()
self.tableView.reloadData()
NSLog("Top Index Path \(hitIndex?.row)")
}
You're overriding number of rows in section to return the count of users, but that is always zero because you never add anything to the dictionary.
The whole point of a PF query table view controller is that it manages the data collection for you, but you're replacing key parts of that and breaking the system. Go back and check the user guide to decide how your subclass needs to work for the effect you want.
// import UIKit
import Parse
import Foundation
class EditFriendsController: UITableViewController {
var allUsers:NSArray = [] // NSArray *allUsers
var currentUser = PFUser.currentUser()
var friends:NSMutableArray = [] // used in FriendsController
var profileImages = [PFFile]()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// PFQuery *query = [PFUser query] in objective C
var query = PFUser.query()
query!.orderByAscending("username")
query!.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error != nil {
// Log details of the failure
println("Error: \(error!)\(error!.userInfo)")
} else {
// The find succeeded.
println("Successfully retrieved \(objects!.count) scores.")
self.allUsers = objects!
// println("\(self.allUsers)")
self.animateTable() // include self.tableView.reloadData()
}
}
self.currentUser = PFUser.currentUser()
}
// MARK: - Table view animate function
func animateTable() {
tableView.reloadData()
let cells = tableView.visibleCells()
let tableHeight:CGFloat = tableView.bounds.size.height
for transformBefore in cells {
let cell: UITableViewCell = transformBefore as! UITableViewCell
cell.transform = CGAffineTransformMakeTranslation(0, tableHeight)
}
var index = 0
for transformAfter in cells {
let cell: UITableViewCell = transformAfter as! UITableViewCell
UIView.animateWithDuration(1.5, delay: 0.05 * Double(index), usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: nil, animations: { () -> Void in
cell.transform = CGAffineTransformMakeTranslation(0, 0)
}, completion: nil)
index += 1
}
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.allUsers.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! EditFriendsProfileViewCell
var user = self.allUsers[indexPath.row] as! PFUser
cell.usernameLabel.text = user.username!
// cell.profileImageView.image = UIImage(named: profileImages[indexPath.row])
if let userPicture = PFUser.currentUser()?["photo"] as? PFFile {
userPicture.getDataInBackgroundWithBlock({
(imageData:NSData?, error:NSError?) -> Void in
var img:UIImageView = UIImageView()
if (error == nil) {
cell.profileImageView.image = UIImage(data: imageData!)
} else {
}
})
}
// image cornerRadius
cell.profileImageView.layer.cornerRadius = 10
cell.profileImageView.clipsToBounds = true
var myFriend = isFriend(user)
cell.accessoryType = myFriend ? .Checkmark : .None
//cell.checkImageView.image = myFriend ? UIImage(named: "checkedFilled.png") : UIImage(named: "checkedWhite.png")
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.tableView.deselectRowAtIndexPath(indexPath, animated: false)
var cell = tableView.cellForRowAtIndexPath(indexPath) as! EditFriendsProfileViewCell
var user = self.allUsers[indexPath.row] as! PFUser
var friendsRelation = self.currentUser!.relationForKey("friendsRelation")
var myFriend = isFriend(user)
if (myFriend) {
// remove process
// 1. Remove the checkmark
cell.accessoryType = UITableViewCellAccessoryType.None
// cell.imageView?.image = UIImage(named: "checkedWhite.png")
// 2. Remove from array of friend
var friend = PFUser()
for friend in self.friends {
if friend.objectId == user.objectId {
self.friends.removeObject(friend)
break;
}
}
// 3. Remove from the backend
friendsRelation.removeObject(user)
} else {
// add them
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
// cell.imageView?.image = UIImage(named: "checkedFilled.png")
self.friends.addObject(user)
friendsRelation.addObject(user)
}
self.currentUser!.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// The post has been added to the user's likes relation.
} else {
// There was a problem, check error.description
println("Error: \(error!)\(error!.userInfo)")
}
}
}
// MARK: - Table view Helper Methods
func isFriend(user: PFUser!) -> Bool {
var friend = PFUser()
for friend in self.friends {
if friend.objectId == user.objectId {
return true;
}
}
return false;
}
}
All profile pictures are loaded as same image although all different stores are stored in Parse.
Please help me.
you are setting photo of currently logged-in user , set user?["photo"] in cellForRowAtIndexPath
if let userPicture = user?["photo"] as? PFFile{
}
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 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.