Why are checkmarks being added in the wrong cell? - ios

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

Related

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

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 }

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
}

issue following / unfollowing users when searched for? Parse

Good Afternoon,
Today I am having some issues with parse.
I have created a UISearchController, loaded my users from parse so I can search for individual ones and I have added a following and unfollowing feature.
My Problem is when I search for a specific user and try to follow him: So I search for a specific user say "test" it shows up as it should, but when I click follow and then go back to parse to see if "I" have followed test I can a different result.
It says I have followed for example "tester" which was the first user created. Its seeming to follow the Cell and now the userId...
After that I manged to get the users in alphabetical order, but same problem here except it follows the first user in alphabetical order for example if I have a username that begins with an "A"!
I'm not sure how to fix this issue, so I'm hoping someone here does..I accept and appreciate all kind of tips and answers!
Heres my code:
class yahTableViewController: UITableViewController, UISearchResultsUpdating {
var users: [PFUser] = [PFUser]()
var followingList: [PFUser] = [PFUser]()
var searchResults: Bool = false
var resultSearchController = UISearchController()
var refresher: UIRefreshControl!
#IBOutlet var userTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.resultSearchController = UISearchController(searchResultsController: nil)
self.resultSearchController.searchResultsUpdater = self
self.resultSearchController.hidesNavigationBarDuringPresentation = false
self.navigationItem.titleView = resultSearchController.searchBar
self.resultSearchController.dimsBackgroundDuringPresentation = false
self.definesPresentationContext = true
self.resultSearchController.searchBar.sizeToFit()
self.resultSearchController.searchBar.barStyle = UIBarStyle.Black
self.resultSearchController.searchBar.tintColor = UIColor.whiteColor()
for subview in self.resultSearchController.searchBar.subviews
{for subsubView in subview.subviews
{if let textField = subsubView as? UITextField
{textField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("Search", comment: ""), attributes: [NSForegroundColorAttributeName: UIColor.whiteColor()])
textField.textColor = UIColor.whiteColor()
}}}
tableView.tableFooterView = UIView()
self.tableView.separatorInset = UIEdgeInsets(top: 10, left: 15, bottom: 10, right: 15)
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "")
refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
self.tableView.addSubview(refresher)
}
//Function used to load the users on first view load or when the UI refresh is performed
private func loadUsers(searchString: String){
func refresh() {
let query = PFUser.query()
query!.whereKey("username", containsString: searchString )
self.searchResults = true
query!.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if (error == nil) {
self.users.removeAll(keepCapacity: false)
self.users += objects as! [PFUser]
self.tableView.reloadData()
} else {
// Log details of the failure
print("search query error: \(error) \(error!.userInfo)")
}
// Now get the following data for the current user
let query = PFQuery(className: "followers")
query.whereKey("follower", equalTo: PFUser.currentUser()!)
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if (error == nil) {
self.followingList.removeAll(keepCapacity: false)
self.followingList += objects as! [PFUser]
self.userTableView.reloadData()
} else
if error != nil {
print("Error getting following: \(error) \(error!.userInfo)")
}
})
}
self.searchResults = false
self.tableView.reloadData()
self.refresher.endRefreshing()
}}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
// Force search if user pushes button
let searchString: String = searchBar.text!.lowercaseString
if (searchString != "") {
loadUsers(searchString)
}
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchBar.text = ""
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
let searchString: String = searchController.searchBar.text!.lowercaseString
if (searchString != "" && !self.searchResults) {
loadUsers(searchString)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.resultSearchController.active) {
return self.users.count
} else {
return self.users.count
// return whatever your normal data source is
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let Cell = tableView.dequeueReusableCellWithIdentifier("Cell")! as UITableViewCell
if (self.resultSearchController.active && self.users.count > indexPath.row) {
let userObject = users[indexPath.row]
Cell.textLabel?.text = userObject.username
for following in followingList {
if following["following"] as? String == PFUser.currentUser()! {
//Add checkbox to cell
Cell.accessoryType = UITableViewCellAccessoryType.Checkmark
break
}}
// bind data to the search results cell
} else {
// bind data from your normal data source
}
return Cell
}
// MARK: - UITableViewDelegate
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let selectedUser = users[indexPath.row] as? PFUser {
// Now get the following/following data for the current user
let query = PFQuery(className: "Followers")
query.whereKey("follower", equalTo: (PFUser.currentUser()?.objectId)!)
query.whereKey("following", equalTo: (selectedUser.objectId)!)
query.getFirstObjectInBackgroundWithBlock({ (object, error) -> Void in
if error != nil && object == nil {
// Means the record doesn't exist
self.insertFollowingRecord(selectedUser, selectedIndexPath: indexPath)
} else {
// Means record is present, so we will delete it
if let followingObject = object {
followingObject.deleteInBackground()
let cell:UITableViewCell = self.userTableView.cellForRowAtIndexPath(indexPath)!
//Remove checkbox from cell
cell.accessoryType = UITableViewCellAccessoryType.None
}
}
})
}
}
private func insertFollowingRecord (selectedUser:PFUser, selectedIndexPath: NSIndexPath) -> Void {
// Now add the data for following in parse
let following:PFObject = PFObject(className: "Followers")
following["following"] = selectedUser.objectId
following["follower"] = PFUser.currentUser()?.objectId
following.saveInBackgroundWithBlock({ (success, error) -> Void in
if success {
let cell:UITableViewCell = self.userTableView.cellForRowAtIndexPath(selectedIndexPath)!
//Add checkbox to cell
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
} else if error != nil {
print("Error getting following: \(error) \(error!.userInfo)")
}
})
}
}
You will want to implement the UISearchResultsUpdating protocol to achieve this. It uses a UISearchController (introduced in iOS 8) which has to be added programmatically instead of through the storyboard, but don't worry, it's pretty straight-forward.
This should get the job done for you
Courtesy of Russel.
class YourTableViewController: UITableViewController, UISearchBarDelegate, UISearchResultsUpdating {
var searchUsers: [PFUser] = [PFUser]()
var userSearchController = UISearchController()
var searchActive: Bool = false
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
self.userSearchController = UISearchController(searchResultsController: nil)
self.userSearchController.dimsBackgroundDuringPresentation = true
// This is used for dynamic search results updating while the user types
// Requires UISearchResultsUpdating delegate
self.userSearchController.searchResultsUpdater = self
// Configure the search controller's search bar
self.userSearchController.searchBar.placeholder = "Search for a user"
self.userSearchController.searchBar.sizeToFit()
self.userSearchController.searchBar.delegate = self
self.definesPresentationContext = true
// Set the search controller to the header of the table
self.tableView.tableHeaderView = self.userSearchController.searchBar
}
// MARK: - Parse Backend methods
func loadSearchUsers(searchString: String) {
var query = PFUser.query()
// Filter by search string
query.whereKey("username", containsString: searchString)
self.searchActive = true
query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]?, error: NSError?) -> Void in
if (error == nil) {
self.searchUsers.removeAll(keepCapacity: false)
self.searchUsers += objects as! [PFUser]
self.tableView.reloadData()
} else {
// Log details of the failure
println("search query error: \(error) \(error!.userInfo!)")
}
self.searchActive = false
}
}
// MARK: - Search Bar Delegate Methods
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
// Force search if user pushes button
let searchString: String = searchBar.text.lowercaseString
if (searchString != "") {
loadSearchUsers(searchString)
}
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
// Clear any search criteria
searchBar.text = ""
// Force reload of table data from normal data source
}
// MARK: - UISearchResultsUpdating Methods
// This function is used along with UISearchResultsUpdating for dynamic search results processing
// Called anytime the search bar text is changed
func updateSearchResultsForSearchController(searchController: UISearchController) {
let searchString: String = searchController.searchBar.text.lowercaseString
if (searchString != "" && !self.searchActive) {
loadSearchUsers(searchString)
}
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.userSearchController.active) {
return self.searchUsers.count
} else {
// return whatever your normal data source is
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("userCell") as! UserCell
if (self.userSearchController.active && self.searchUsers.count > indexPath.row) {
// bind data to the search results cell
} else {
// bind data from your normal data source
}
return cell
}
// MARK: - UITableViewDelegate
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
if (self.userSearchController.active && self.searchUsers.count > 0) {
// Segue or whatever you want
} else {
// normal data source selection
}
}
}

Retrieving data from parse in NSMutable array and then get the data from the cells where the button has been tapped

So this is how I'm retrieving all the data and then added a custom button this way :
import UIKit
class userListTableViewController: UITableViewController {
var data:NSMutableArray = NSMutableArray()
func loadData() {
data.removeAllObjects()
var userQuery = PFUser.query()
userQuery?.orderByAscending("createdAt")
userQuery?.findObjectsInBackgroundWithBlock({ (objects, erroe) -> Void in
if let objects = objects {
for object in objects {
if let user = object as? PFUser {
if user.objectId != PFUser.currentUser()?.objectId {
self.data.addObject(object)
}
}
}
}
self.tableView.reloadData()
})
}
override func viewDidLoad() {
super.viewDidLoad()
loadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
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
// Usernames and gender..
myCell.fullName.text = userData.objectForKey("fullName") as! String!
myCell.genderLabel.text = userData.objectForKey("gender") as! String!
// Profile pictures..
let profilePics = userData.objectForKey("profilePicture") as! PFFile
profilePics.getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
myCell.dp.image = downloadedImage
}
}
myCell.followButtton.removeTarget(nil, action: nil, forControlEvents: UIControlEvents.AllEvents)
myCell.followButtton.addTarget(self, action: "followButtonTapped:", forControlEvents: UIControlEvents.TouchUpInside)
return myCell
}
// IBActions..
func followButtonTapped(sender:AnyObject) {
let buttonPosition = sender.convertPoint(CGPointZero, toView: self.tableView)
let indexPath = self.tableView.indexPathForRowAtPoint(buttonPosition)
if indexPath != nil {
if let cell = self.tableView.cellForRowAtIndexPath(indexPath!) as? userListTableViewCell {
cell.followButtton.setTitle("unfollow", forState: UIControlState.Normal)
var followers:PFObject = PFObject(className: "Followers")
followers["follower"] = PFUser.currentUser()?.objectId
followers["user"] = //*********************** here i want to save the objectId of the user being tapped on. want to get the NSMutableArray index from the indexPath
}
println(indexPath!)
}
}
my problem is there where you see ************************. now like in cellForRowAtIndexPath I've used this to show the data :
let userData:PFObject = self.data.objectAtIndex(indexPath.row) as! PFObject
same like this i want to do it in func followButton(sender:AnyObject).
You should not call self.tableView.reloadData() in the for loop, you should do that only once at the end of the for loop when all the data is loaded.
self.data.objectAtIndex(indexPath.row) this worked.

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!")
}

Resources