Swift Thread1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) - ios

There is a SS of error
This happened after add refresh method in to viewDidLoad for pull to refresh . Im using parse.com and that followers table is empty.
I found some questions about some error. But i didn't found anything same as my question or maybe i don't understand.
How can i fix this what is the problem ?
import UIKit
import Parse
class TableViewController: UITableViewController {
var usernames = [""]
var userids = [""]
var isFollowing = ["":false]
var refresher: UIRefreshControl!
func refresh() {
var query = PFUser.query()
query?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let users = objects {
self.usernames.removeAll(keepCapacity: true)
self.userids.removeAll(keepCapacity: true)
self.isFollowing.removeAll(keepCapacity: true)
for object in users {
if let user = object as? PFUser {
if user.objectId! != PFUser.currentUser()?.objectId {
self.usernames.append(user.username!)
self.userids.append(user.objectId!)
var query = PFQuery(className: "followers")
query.whereKey("follower", equalTo: (PFUser.currentUser()?.objectId)!)
query.whereKey("following", equalTo: user.objectId!)
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
if objects.count > 0 {
self.isFollowing[user.objectId!] = true
} else {
self.isFollowing[user.objectId!] = false
}
}
if self.isFollowing.count == self.usernames.count {
self.tableView.reloadData()
self.refresher.endRefreshing()
}
})
}
}
}
}
})
}
override func viewDidLoad() {
super.viewDidLoad()
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Pull to refresher")
refresher.addTarget(self , action: "refresh" , forControlEvents: UIControlEvents.ValueChanged)
self.tableView.addSubview(refresher)
refresh()
}
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 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 usernames.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = usernames[indexPath.row]
let followedOnjectId = userids[indexPath.row]
if isFollowing[followedOnjectId] == true {
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var cell:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
let followedOnjectId = userids[indexPath.row]
if isFollowing[followedOnjectId] == false{
isFollowing[followedOnjectId] = true
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
var following = PFObject(className: "followers")
following["following"] = userids[indexPath.row]
following["follower"] = PFUser.currentUser()?.objectId
following.saveInBackground()
}else
{
isFollowing[followedOnjectId] = false
cell.accessoryType = UITableViewCellAccessoryType.None
var query = PFQuery(className: "followers")
query.whereKey("follower", equalTo: PFUser.currentUser()!.objectId!)
query.whereKey("following", equalTo: userids[indexPath.row])
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for objects in objects {
objects.deleteInBackground()
}
}
})
}
}
}

(PFUser.currentUser()?.objectId)!
or the query-var is nil. That causes the exception.
You should probably use the if let construct
if let objectId = PFUser.currentUser()?.objectId {
query.whereKey("follower", equalTo: objectId)
}
or if the code should be just executed when all the values exist you can use the guard keyword.
guard let a = optionalType?.variable?.a, b = optionalType?.variable?.b else { return }

Related

Why are checkmarks being added in the wrong cell?

I am creating a view that shows a list of users. The current user is able to click on one of the cells, thus following or unfollowing the user in that cell. For some reason, checkmarks are showing up in cells that should not have the checkmark(meaning the current user is following someone that he really isn't). The images for the users are also incorrect. I imagine the reason for that is related to the checkmark error. What am I doin wrong? PLEASE HELP!
import UIKit
import Parse
class TableViewController: UITableViewController {
var refresher: UIRefreshControl!
var usernames = [""]
var userIds = [""]
var userPics = [String:PFFile]()
var isFollowing = ["":false]
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.hidesBackButton = true
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
self.tableView.addSubview(refresher)
refresh()
}
func refresh (){
let query = PFUser.query()
query?.findObjectsInBackgroundWithBlock({ (object, error) -> Void in
if let users = object {
self.usernames.removeAll(keepCapacity: true)
self.userIds.removeAll(keepCapacity: true)
self.isFollowing.removeAll(keepCapacity: true)
self.userPics.removeAll(keepCapacity: true)
for objects in users {
if let user = objects as? PFUser {
if user.objectId != PFUser.currentUser()?.objectId {
self.usernames.append(user.username!)
self.userIds.append(user.objectId!)
if let image = user["profileImage"] {
self.userPics[user.objectId!] = image as? PFFile
}
let query = PFQuery(className: "Followers")
query.whereKey("following", equalTo: user.objectId!)
query.whereKey("follower", equalTo: (PFUser.currentUser()!.objectId)!)
query.findObjectsInBackgroundWithBlock({ (object, error) -> Void in
if let object = object {
if object.count > 0 {
self.isFollowing[user.objectId!] = true
} else {
self.isFollowing[user.objectId!] = false
}
}
if self.isFollowing.count == self.usernames.count {
print(self.isFollowing)
print(self.userIds)
self.tableView.reloadData()
self.refresher.endRefreshing()
}
})
}
}
}
}
})
}
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 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 usernames.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UsersTableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UsersTableViewCell
cell.userLabel.text = usernames[indexPath.row]
if isFollowing[userIds[indexPath.row]] == true {
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
}
cell.userImage.frame = CGRectMake(0, 0, 100, 100)
cell.userImage.clipsToBounds = true
cell.userImage.layer.cornerRadius = cell.userImage.frame.height/2
if userPics[userIds[indexPath.row]] != nil {
userPics[userIds[indexPath.row]]!.getDataInBackgroundWithBlock { (data, error) -> Void in
if let data = data {
cell.userImage.image = UIImage(data: data)
}
}
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell: UsersTableViewCell = tableView.cellForRowAtIndexPath(indexPath)! as! UsersTableViewCell
if isFollowing[userIds[indexPath.row]] == false {
isFollowing[userIds[indexPath.row]] = true
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
let following = PFObject(className: "Followers")
following["following"] = userIds[indexPath.row]
following["follower"] = PFUser.currentUser()?.objectId
following.saveInBackground()
} else {
isFollowing[userIds[indexPath.row]] = false
cell.accessoryType = UITableViewCellAccessoryType.None
let query = PFQuery(className: "Followers")
query.whereKey("following", equalTo: userIds[indexPath.row])
query.whereKey("follower", equalTo: (PFUser.currentUser()?.objectId)!)
query.findObjectsInBackgroundWithBlock({ (object, error) -> Void in
if let object = object {
for users in object {
users.deleteInBackground()
}
}
})
}
}
}
Like Michael said, you need to clear the checkmark, try with this code instead of your if
cell.accessoryType = isFollowing[userIds[indexPath.row]] ? UITableViewCellAccessoryType.Checkmark : UITableViewCellAccessoryType.None

Why are my feed cells duplicating?

I am using this code to create a feed view that shows users, images, and comments similar to instagram. For some reason, the cells on the feed are duplicating the current user's posts. Not only that, but it is also putting the incorrect username with the images on the duplicate cells. What am I doing wrong?
import UIKit
import Parse
class FeedTableViewController: UITableViewController {
var usersBeingFollowed = [String]()
var imageFiles = [PFFile]()
var imageComment = [""]
var usernames = [String]()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.hidesBackButton = true
let getFollowedUsersQuery = PFQuery(className: "Followers")
getFollowedUsersQuery.whereKey("follower", equalTo: PFUser.currentUser()!.objectId!)
getFollowedUsersQuery.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
self.usernames.removeAll(keepCapacity: true)
self.imageComment.removeAll(keepCapacity: true)
self.imageFiles.removeAll(keepCapacity: true)
self.usersBeingFollowed.removeAll(keepCapacity: true)
if let objects = objects {
for object in objects {
let followedUser = object["following"] as! String
let getFollowedUsers = PFQuery(className: "Post")
getFollowedUsers.whereKey("userId", equalTo: followedUser)
let getCurrentUser = PFQuery(className: "Post")
getCurrentUser.whereKey("userId", equalTo: (PFUser.currentUser()?.objectId)!)
var query = PFQuery.orQueryWithSubqueries([getFollowedUsers,getCurrentUser])
query.findObjectsInBackgroundWithBlock({ (imageObjects, error) -> Void in
if let objects = imageObjects {
for images in objects {
let userQuery = PFUser.query()
userQuery?.whereKey("_id", equalTo: images["userId"])
userQuery?.findObjectsInBackgroundWithBlock({ (user, error) -> Void in
print(user)
if let user = user {
for username in user {
self.usernames.append(username["username"] as! String)
}
}
})
self.imageFiles.append(images["imageFile"] as! PFFile)
self.imageComment.append(images["imageComment"] as! String)
self.tableView.reloadData()
}
}
})
}
}
}
}
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 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 usernames.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("imagePostCell", forIndexPath: indexPath) as! cell
if imageFiles.count > 0{
myCell.userLabel.text = "\(usernames[indexPath.row]) completed the \(imageComment[indexPath.row]) challenge!"
imageFiles[indexPath.row].getDataInBackgroundWithBlock({ (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
myCell.imagePost.image = downloadedImage
// self.tableView.reloadData()
}
})
}
return myCell
}
You should reset the cell property before add new values, you can use
prepareForReuse()
More info on Apple Doc https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableViewCell_Class/index.html#//apple_ref/occ/instm/UITableViewCell/prepareForReuse
It will be obviously, generate the duplicate content because you have put the condition that if imageFiles.count > 0 then the data will be displayed.
But what when there are no images? It will definitely take the value from reusable UITableViewCell. Check the below change:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("imagePostCell", forIndexPath: indexPath) as! cell
if imageFiles.count > 0{
myCell.userLabel.text = "\(usernames[indexPath.row]) completed the \(imageComment[indexPath.row]) challenge!"
imageFiles[indexPath.row].getDataInBackgroundWithBlock({ (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
myCell.imagePost.image = downloadedImage
// self.tableView.reloadData()
}
})
}else{
myCell.userLabel.text = "Put What You Want Here" //make just nil
myCell.imagePost.image = UIImage(name: "placeholder.png") //Some Placeholder image when there is no data
}
return myCell
}

UIButtons in tableViewCell, how to get already following users from Parse using Swift

I've been working on it from 2 weeks now, I've Instagram like app, where user can signUp and Login using Parse backend. Now after signUp a segue is made for the next screen called userListTableViewController here users will be allowed to follow the already existing users. Now i trying to retrieve data in NSMutableArray and show them as follows:
import UIKit
class userListTableViewController: UITableViewController {
var data:NSMutableArray = NSMutableArray()
var isFollowing = [PFObject:Bool]()
func loadData() {
data.removeAllObjects()
isFollowing.removeAll(keepCapacity: true)
var userQuery = PFUser.query()
userQuery?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if error != nil {
} else {
if let objects = objects {
for object in objects {
if let user = object as? PFObject {
if user.objectId != PFUser.currentUser()?.objectId {
self.data.addObject(user)
var followerQuery: PFQuery = PFQuery(className: "Followers")
followerQuery.whereKey("follower", equalTo: PFUser.currentUser()!)
followerQuery.whereKey("user", equalTo: user)
followerQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
if objects.count > 0 {
self.isFollowing[user] = true
} else {
self.isFollowing[user] = false
}
}
if self.isFollowing.count == self.data.count {
self.tableView.reloadData()
}
})
}
}
}
}
}
})
}
override func viewDidLoad() {
super.viewDidLoad()
loadData()
}
/*
var array:NSMutableArray = NSMutableArray(array: self.data.reverseObjectEnumerator().allObjects)
self.data = array as NSMutableArray
self.tableView.reloadData()
*/
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// 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 data.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("users", forIndexPath: indexPath) as! userListTableViewCell
let userData:PFObject = self.data.objectAtIndex(indexPath.row) as! PFObject
myCell.fullName.text = userData["objectId"] as! String!
myCell.genderLabel.text = userData["gender"] as! String!
// var array:NSMutableArray = NSMutableArray(array: self.data.reverseObjectEnumerator().allObjects)
// self.data = array as NSMutableArray
let followedId = // What should i use here?? *****************
if isFollowing[followedId] == true { // ERROR!! not able to use followedId here.. how should i give a value so that it will check the particular user's objectId and isFollowing Bool value. ******************
myCell.followButtton.setTitle("unfollow", forState: UIControlState.Normal)
} else {
myCell.followButtton.setTitle("follow", forState: UIControlState.Normal)
}
userData["profilePicture"]?.getDataInBackgroundWithBlock({ (data, error) -> Void in
if let downloadeImage = UIImage(data: data!) {
myCell.dp.image = downloadeImage
}
myCell.followButtton.tag = indexPath.row
myCell.followButtton.addTarget(self, action: "followButtonTapped:", forControlEvents: UIControlEvents.TouchUpInside)
})
return myCell
}
// IBActions..
func followButtonTapped(sender: UIButton){
let userData:PFObject = self.data.objectAtIndex(sender.tag) as! PFObject
let followedId = userData["objectId"] as! PFObject
if isFollowing[followedId] == false {
isFollowing[followedId] = true
sender.setTitle("unfollow", forState: UIControlState.Normal)
let getObjectByIdQuery = PFUser.query()
getObjectByIdQuery?.whereKey("objectId", equalTo: userData.objectId!)
getObjectByIdQuery?.getFirstObjectInBackgroundWithBlock({ (foundObject:PFObject?, error:NSError?) -> Void in
if let object = foundObject {
var followers:PFObject = PFObject(className: "Followers")
followers["user"] = object
followers["follower"] = PFUser.currentUser()
followers.saveInBackgroundWithBlock({ (success, error) -> Void in
if error != nil {
println(error)
} else {
println("saved")
}
})
}
})
} else {
isFollowing[followedId] = false
sender.setTitle("follow", forState: UIControlState.Normal)
var query:PFQuery = PFQuery(className: "Followers")
query.whereKey("follower", equalTo: PFUser.currentUser()!)
query.whereKey("user", equalTo: data[sender.tag])
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
object.deleteInBackgroundWithBlock({ (success, error) -> Void in
if error != nil {
println(error)
} else {
println("deleted")
}
})
}
}
})
}
}
}
shown the problem in the code as comment.. or else can you please suggest me some other way better than this.. i've tried to retrieve data in arrays also, there also i'm getting problem for the "follow" buttons. You can see the problem here.. Not able to reload data properly when retrieving objects from Parse .. Please check this link too..
Please help me out here.. Thanks..
Edit: I just want to make the user list with there gender full name and profile picture, and want to allow user to follow them with a button "follow" on each cell.. and if the app restarts, the users which have been already followed by the current user must be marked as "unfollow" to unfollow the user if current user wants it..
check the comments in the code.. error is there where you see "***************" it's in cellForRowAtIndexPath
Instead of playing with PFUser, arrays and dictionaries, create a class User in application side.
class User: NSObject {
var pfUser : PFObject?
var isFollowing : Bool = false
}
And in loadData method,
func loadData() {
// **************** Your Codes ********************
if user.objectId != PFUser.currentUser()?.objectId {
var otherUser = User()
otherUser.pfUser = user
// **************** Your Codes ********************
followerQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
if objects.count > 0 {
otherUser.isFollowing = true
}
}
})
self.data.addObject(otherUser)
}
}
Then use the single mutableArray data to populate tableView.

swift: fatal error: unexpectedly found nil while unwrapping an Optional value (lldb), Thread 1

I keep getting this fatal error when I run the simulator and I do not know how to solve it. I am creating a mock Instagram project with Parse and for some reason I get a fatal error and a THREAD 1 on:
query.whereKey("follower", equalTo: PFUser.currentUser()!.objectId!)
I know this is a common problem, because I looked through numerous questions that contains this fatal error. However, I am very new to Swift programming so I was getting confused and would appreciate it if anyone could help me out, Thanks!
import UIKit
import Parse
class TableViewController: UITableViewController {
var usernames = [""]
var userids = [""]
var isFollowing = ["":false]
override func viewDidLoad() {
super.viewDidLoad()
var query = PFUser.query()
query?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let users = objects {
self.usernames.removeAll(keepCapacity: true)
self.userids.removeAll(keepCapacity: true)
self.isFollowing.removeAll(keepCapacity: true)
for object in users {
if let user = object as? PFUser {
if user.objectId! != PFUser.currentUser()?.objectId {
self.usernames.append(user.username!)
self.userids.append(user.objectId!)
var query = PFQuery(className: "followers")
query.whereKey("follower", equalTo: PFUser.currentUser()!.objectId!)
query.whereKey("following", equalTo: user.objectId!)
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
if objects.count > 0 {
self.isFollowing[user.objectId!] = true
} else {
self.isFollowing[user.objectId!] = false
}
}
if self.isFollowing.count == self.usernames.count {
self.tableView.reloadData()
}
})
}
}
}
}
})
}
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 usernames.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = usernames[indexPath.row]
let followedObjectId = userids[indexPath.row]
if isFollowing[followedObjectId] == true {
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var cell:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
let followedObjectId = userids[indexPath.row]
if isFollowing[followedObjectId] == false {
isFollowing[followedObjectId] = true
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
var following = PFObject(className: "followers")
following["following"] = userids[indexPath.row]
following["follower"] = PFUser.currentUser()?.objectId
following.saveInBackground()
} else {
isFollowing[followedObjectId] = false
cell.accessoryType = UITableViewCellAccessoryType.None
var query = PFQuery(className: "followers")
query.whereKey("follower", equalTo: PFUser.currentUser()!.objectId!)
query.whereKey("following", equalTo: userids[indexPath.row])
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
object.deleteInBackground()
}
}
})
}
}
}
You are probably not logged as any user so PFUser.currentUser() is returning nil and when you force unwrap it creates the error as you cannot unwrap a nil value.
Check first if there is a user logged using:
if let user = PFUser.currentUser(){
println("User logged, lets do this")
var query = PFQuery(className: "followers")
query.whereKey("follower", equalTo: PFUser.currentUser()!.objectId!)
query.whereKey("following", equalTo: userids[indexPath.row])
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
object.deleteInBackground()
}
}
})
} else {
println("No user logged, ops!")
}

Querying and updating votes with Parse?

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 :)

Resources