I'm using a Parse account to post images, messages and username to a prototype cell. For some reason my username string is staying empty and thus not posting to the cell. Can you help? I'm fairly new to coding so this one has just stumped me.
import UIKit
import Parse
class FeedTableViewController: UITableViewController {
var messages = [String]()
var usernames = [String]()
var imageFiles = [PFFile]()
var users = [String: String]()
var refresher: UIRefreshControl!
#IBAction func logout(sender: AnyObject) {
PFUser.logOut()
var currentUser = PFUser.currentUser()
performSegueWithIdentifier("logout", sender: self)
}
func swiped(gesture:UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Right:
performSegueWithIdentifier("feedSwipe", sender: self)
//case UISwipeGestureRecognizerDirection.Up:
//print("User Swiped Up")
//case UISwipeGestureRecognizerDirection.Down:
//print("User Swiped Down")
case UISwipeGestureRecognizerDirection.Left:
performSegueWithIdentifier("feedSwipe", sender: self)
default:
break
}
}
}
func refresh() {
var query = PFUser.query()
query?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let users = objects {
self.messages.removeAll(keepCapacity: true)
self.users.removeAll(keepCapacity: true)
self.imageFiles.removeAll(keepCapacity: true)
self.usernames.removeAll(keepCapacity: true)
for object in users {
if let user = object as? PFUser {
self.users[user.objectId!] = user.username!
}
}
}
var getFollowedUsersQuery = PFQuery(className: "followers")
getFollowedUsersQuery.whereKey("follower", equalTo: PFUser.currentUser()!.objectId!)
getFollowedUsersQuery.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let objects = objects {
for object in objects {
var followedUser = object["following"] as! String
var query = PFQuery(className: "Post")
query.whereKey("userId", equalTo: followedUser)
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
self.messages.append(object["message"]! as! String)
self.imageFiles.append(object["imageFile"]! as! PFFile)
self.usernames.append(self.users[object["userId"] as! String]!)
//self.usernames.append(followedUser)
self.tableView.reloadData()
self.refresher.endRefreshing()
//print(followedUser)
}
}
})
}
}
}
})
}
override func viewDidLoad() {
super.viewDidLoad()
let swipeRight = UISwipeGestureRecognizer(target: self, action: "swiped:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
self.view.addGestureRecognizer(swipeRight)
let swipeUp = UISwipeGestureRecognizer(target: self, action: "swiped:")
swipeUp.direction = UISwipeGestureRecognizerDirection.Up
self.view.addGestureRecognizer(swipeUp)
let swipeDown = UISwipeGestureRecognizer(target: self, action: "swiped:")
swipeDown.direction = UISwipeGestureRecognizerDirection.Down
self.view.addGestureRecognizer(swipeDown)
let swipeLeft = UISwipeGestureRecognizer(target: self, action: "swiped:")
swipeLeft.direction = UISwipeGestureRecognizerDirection.Left
self.view.addGestureRecognizer(swipeLeft)
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
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 myCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! cell
imageFiles[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
myCell.postedImage.image = downloadedImage
}
}
myCell.username.text = usernames[indexPath.row]
myCell.message.text = messages[indexPath.row]
return myCell
}
Related
my self.tableView reload data function is not being called for some reason. Here is my whole tableview code:
class NewMessageController: UITableViewController {
let currentUser: String = (FIRAuth.auth()?.currentUser?.uid)!
var ref = FIRDatabaseReference()
let cellId = "cellId"
var users = [User]()
var groupUserArray = [GlobalVariables.UserArray]
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
getCurrentUserSchoolOrWorkAddressAndDisplayOtherUsers()
navigationItem.title = "New Message"
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: #selector(cancelButton))
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Select", style: .Plain, target: self, action: #selector(selectButton))
// fetchUserAndDisplay()
tableView.registerClass(UserCell.self, forCellReuseIdentifier: cellId)
}
var messagesController2 = MessagingViewController?()
func selectButton() {
tableView.allowsMultipleSelectionDuringEditing = true
tableView.setEditing(true, animated: false)
if tableView.allowsMultipleSelectionDuringEditing == true {
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Create", style: .Plain, target: self, action: #selector(createGroupMessagesButton))
}
}
func cancelButton() {
if tableView.allowsMultipleSelectionDuringEditing == true {
tableView.allowsMultipleSelectionDuringEditing = false
tableView.setEditing(false, animated: true)
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Select", style: .Plain, target: self, action: #selector(selectButton))
}
else {
dismissViewControllerAnimated(true, completion: nil)
}
}
func fetchUserAndDisplay() {
FIRDatabase.database().reference().child("users").observeEventType(.ChildAdded, withBlock: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = User()
user.id = snapshot.key
user.setValuesForKeysWithDictionary(dictionary)
self.users.append(user)
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}
}, withCancelBlock: nil)
}
func createGroupMessagesButton() {
dismissViewControllerAnimated(true) {
if let selectedUserRows = self.tableView.indexPathsForSelectedRows {
self.groupUserArray.append(selectedUserRows)
for index in selectedUserRows {
let text = self.users[index.row]
self.messagesController?.showChatLogController(text)
}
}
}
}
func getCurrentUserSchoolOrWorkAddressAndDisplayOtherUsers() {
let currentUser = (FIRAuth.auth()?.currentUser!)
let userID = currentUser?.uid
FIRDatabase.database().reference().child("users").child(userID!).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
let schoolOrWorkAddress = snapshot.value!["schoolOrWorkAddress"] as! String
FIRDatabase.database().reference().child("schoolOrWorkAddress").child(schoolOrWorkAddress).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
if(!snapshot.exists()){
return
}
let locations = snapshot.value! as! NSDictionary
for (index, location) in locations.enumerate() {
FIRDatabase.database().reference().child("users").child(location.key as! String).observeEventType(.ChildAdded, withBlock: { (snapshot: FIRDataSnapshot) in
if(snapshot.exists()){
print(snapshot)
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = User()
user.id = snapshot.key
user.setValuesForKeysWithDictionary(dictionary)
self.users.append(user)
print(self.users)
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}
}
}, withCancelBlock: nil)
}
})
})
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users.count
}
var messagesController = MessagingViewController?()
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if tableView.allowsMultipleSelectionDuringEditing != true {
dismissViewControllerAnimated(true) {
let user = self.users[indexPath.row]
self.messagesController?.showChatLogController(user)
}
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellId, forIndexPath: indexPath) as! UserCell
let user = users[indexPath.row]
cell.textLabel?.text = user.fullName
cell.detailTextLabel?.text = user.email
if let userPhoto = user.userPhoto {
cell.profileImageView.loadImageUsingCacheWithUrlString(userPhoto)
}
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 72
}
}
The problem however is occurring right here:
for (index, location) in locations.enumerate() {
FIRDatabase.database().reference().child("users").child(location.key as! String).observeEventType(.ChildAdded, withBlock: { (snapshot: FIRDataSnapshot) in
if(snapshot.exists()){
print(snapshot)
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = User()
user.id = snapshot.key
user.setValuesForKeysWithDictionary(dictionary)
self.users.append(user)
print(self.users)
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}
}
}, withCancelBlock: nil)
}
The above reloadData function is not being called for some reason!
The following is a breakpoint picture:
Does anyone have any thoughts on why this is happening?
Any help would be appreciated
In my app users are able to log in/ sign up by creating a username and password or by logging in with Facebook. Parse stores their username and password. It does the same for Facebook, but it stores the users token (I think) instead of the username. I then display the users names in a table view, but the Facebook users show up as a user token like : Afjkd233edJ instead of their user name. I am using Facebook graph api also, it stores the name under name in my class User. I am not able however to get that name to post instead of the token thing. Here is the code I am using in my View controller which handles login and sign up and then bellow that is my table view controller which display the users and who they are following or not following. EDIT: I forgot to to mention that I am using parse server and have migrated it over to Heroku and am using the mongoldb dyno.
VIEWCONTROLLER
import UIKit
import Parse
import ParseFacebookUtilsV4
class ViewController: UIViewController {
var signupActive = true
#IBOutlet weak var username: UITextField!
#IBOutlet weak var password: UITextField!
#IBOutlet weak var signupButton: UIButton!
#IBOutlet weak var registeredText: UILabel!
#IBOutlet weak var loginButton: UIButton!
var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView()
func displayAlert(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction((UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
})))
self.presentViewController(alert, animated: true, completion: nil)
}
#IBAction func signUp(sender: AnyObject) {
if username.text == "" || password.text == "" {
displayAlert("Error in form", message: "Please enter a username and password")
} else {
activityIndicator = UIActivityIndicatorView(frame: CGRectMake(0, 0, 50, 50))
activityIndicator.center = self.view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
UIApplication.sharedApplication().beginIgnoringInteractionEvents()
var errorMessage = "Please try again later"
if signupActive == true {
let user = PFUser()
user.username = username.text
user.password = password.text
user.signUpInBackgroundWithBlock({ (success, error) -> Void in
self.activityIndicator.stopAnimating()
UIApplication.sharedApplication().endIgnoringInteractionEvents()
if error == nil {
// Signup successful
//self.performSegueWithIdentifier("login", sender: self)
let appDelegate = UIApplication.sharedApplication().delegate! as! AppDelegate
var initialViewController = self.storyboard!.instantiateViewControllerWithIdentifier("myTabbarControllerID") as! UIViewController
appDelegate.window?.rootViewController = initialViewController
appDelegate.window?.makeKeyAndVisible()
} else {
if let errorString = error!.userInfo["error"] as? String {
errorMessage = errorString
}
self.displayAlert("Failed SignUp", message: errorMessage)
}
})
} else {
PFUser.logInWithUsernameInBackground(username.text!, password: password.text!, block: { (user, error) -> Void in
self.activityIndicator.stopAnimating()
UIApplication.sharedApplication().endIgnoringInteractionEvents()
if user != nil {
// Logged In!
//self.performSegueWithIdentifier("login", sender: self)
let appDelegate = UIApplication.sharedApplication().delegate! as! AppDelegate
var initialViewController = self.storyboard!.instantiateViewControllerWithIdentifier("myTabbarControllerID") as! UIViewController
appDelegate.window?.rootViewController = initialViewController
appDelegate.window?.makeKeyAndVisible()
} else {
if let errorString = error!.userInfo["error"] as? String {
errorMessage = errorString
}
self.displayAlert("Failed Login", message: errorMessage)
}
})
}
}
}
#IBAction func logIn(sender: AnyObject) {
if signupActive == true {
signupButton.setTitle("Log In", forState: UIControlState.Normal)
registeredText.text = "Not registered?"
loginButton.setTitle("Sign Up", forState: UIControlState.Normal)
signupActive = false
} else {
signupButton.setTitle("Sign Up", forState: UIControlState.Normal)
registeredText.text = "Already registered?"
loginButton.setTitle("Login", forState: UIControlState.Normal)
signupActive = true
}
}
#IBAction func faceBookLogIn(sender: AnyObject) {
let permissions = ["public_profile"]
PFFacebookUtils.logInInBackgroundWithReadPermissions(permissions, block: {
(user: PFUser?, error: NSError?) -> Void in
if let error = error {
print(error)
} else {
let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, gender"])
graphRequest.startWithCompletionHandler( {
(connection, result, error) -> Void in
if error != nil {
print(error)
} else if let result = result {
PFUser.currentUser()?["name"] = result["name"]!
PFUser.currentUser()?.saveInBackground()
let userId = result["id"]! as! String
}
})
if let user = user {
//self.performSegueWithIdentifier("login", sender: self)
let appDelegate = UIApplication.sharedApplication().delegate! as! AppDelegate
var initialViewController = self.storyboard!.instantiateViewControllerWithIdentifier("myTabbarControllerID") as! UIViewController
appDelegate.window?.rootViewController = initialViewController
appDelegate.window?.makeKeyAndVisible()
}
}
})
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewDidAppear(animated: Bool) {
if let username = PFUser.currentUser()?.username {
let appDelegate = UIApplication.sharedApplication().delegate! as! AppDelegate
var initialViewController = self.storyboard!.instantiateViewControllerWithIdentifier("myTabbarControllerID") as! UIViewController
appDelegate.window?.rootViewController = initialViewController
appDelegate.window?.makeKeyAndVisible()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
TABELVIEW
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 refresh")
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 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()
}
}
})
}
}
}
I'm having issues fetching the users images from parse and loading them on a table view.. I think it is something to do with the userId /Strings and pointer buissness!
The images upload fine to parse and I can see them, but I cannot seem to download them. My code is definetly the problem, I just can't figure out which part.
On parse the userId is a pointer to the user class, so I'm pretty sure I've done something wrong connecting it all..! I'm new to swift & Parse so I still have a bit of difficulty understanding it all.
Here's my code below, if anyone understands the problem I would love it if you could tell me!!
import UIKit
import Parse
class TimelineTableViewController: UITableViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIPopoverPresentationControllerDelegate {
#IBOutlet var feedTableView: UITableView!
var refresher:UIRefreshControl!
var titles = [String]()
var username = [String]()
var imageFiles = [PFFile]()
var users = [String: String]()
override func viewDidLoad() {
super.viewDidLoad()
let query = PFUser.query()
query?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let users = objects {
self.titles.removeAll(keepCapacity: true)
self.imageFiles.removeAll(keepCapacity: true)
self.users.removeAll(keepCapacity: true)
self.username.removeAll(keepCapacity: true)
for object in users {
if let user = object as? PFUser {
self.users[user.objectId!] = user.username!
}
}
}
let getFollowedUsersQuery = PFQuery(className: "followers")
getFollowedUsersQuery.whereKey("follower", equalTo: PFUser.currentUser()!)
getFollowedUsersQuery.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let objects = objects {
for object in objects {
let followedUser = object ["following"] as! String
let query = PFQuery(className: "Post")
query.whereKey("userId", equalTo: followedUser)
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
self.titles.append(object["title"]! as! String)
self.imageFiles.append(object["imageFile"]! as! PFFile)
self.username.append(self.users[object["userId"] as! String]!)
self.tableView.reloadData()
} }}) } } } })
// Add the refresher
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "")
refresher.addTarget(self, action: "refreshData", forControlEvents: UIControlEvents.ValueChanged)
// Add the refresher as a sub view on the tableview
self.feedTableView.addSubview(refresher)
}
func refreshData() -> Void {
self.refresher.endRefreshing()}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func blogPost(sender: AnyObject) {
}
#IBAction func CameraPopover(sender: AnyObject) {
self.performSegueWithIdentifier("cameraPopover", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "cameraPopover"
{
let vc = segue.destinationViewController
let controller = vc.popoverPresentationController
if controller != nil
{
controller?.delegate = self
vc.preferredContentSize = CGSizeMake(50, 90)
}
}}
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
return.None
}
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 username.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let postCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! TimelineTableViewCell
imageFiles[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
postCell.postedImage.image = downloadedImage
}
}
postCell.usernameLabel.text = username[indexPath.row]
postCell.titleLabel.text = titles[indexPath.row]
return postCell
}
}
The issue you mentioned with the userId pointer is here:
let followedUser = object ["following"] as! String
let query = PFQuery(className: "Post")
query.whereKey("userId", equalTo: followedUser)
You mentioned that the userId column of the Post class is a User pointer, however you reference it as a string with followedUser.
With regards to the images not displaying properly, they will not be displayed until you refresh the UI. You are using the correct code to load the data which is
imageFiles[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
postCell.postedImage.image = downloadedImage
}
However, the issue is that since the data is loaded asynchronously, the postCell will be returned to the table before the data has been fetched. The key piece that's missing is to refresh the table using self.tableView.reloadData() in the completion handler.
imageFiles[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
postCell.postedImage.image = downloadedImage
self.tableView.reloadData()
}
Alternatively, I would recommend looking into using a PFImageView from the ParseUI framework. You assign each of the PFFiles to a PFImageView in the completion of the query and then call loadInBackground on each PFImageView. The PFImageView class automatically handles updating the images once the data has been loaded.
I have pull to refresh functionality in TableView Controller, which lists all usernames and who the current user is following (indicated by a checkmark at the end of each row). Here is my refresh function:
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()
}
})
}
}
}
}
})
}
It's called in my viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
//pull to refresh funcationlity
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
self.tableView.addSubview(refresher)
refresh()
}
The problem is that when I delete an item manually from the Parse.com database, and pull to refresh in the list view, it does not update. Here are my tableview functions:
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()
print(object)
}
}
})
}
}
I keep receiving the following error:
in the logs i get
unexpectedly found nil while unwrapping an Optional value
the reason im having trouble with this is because i ran this code earlier and it worked fine can somebody please help and tell me where im going wrong in the code?
here is the full code
import UIKit
import Parse
class HomePage: UITableViewController {
var images = [UIImage]()
var titles = [String]()
var imageFile = [PFFile]()
var voteCounter = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
println(PFUser.currentUser())
var query = PFQuery(className:"Post")
var voteCount = PFObject(className: "Post")
voteCount["voteCounter"] = voteCounter
voteCount.saveInBackground()
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock {(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
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()
}
} else {
// Log details of the failure
println(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"
myCell.votes.text = "\(voteCounter)"
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 {
var voteCounter = 0
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Right:
voteCounter += 1
println("Swiped right")
case UISwipeGestureRecognizerDirection.Left:
voteCounter -= 1
println("Swiped Left")
default:
break
}
}
}
}
also any further advice or comments would be appreciated im fairly new to programming
Try this.
query.findObjectsInBackgroundWithBlock {(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
println("Successfully retrieved \(objects!.count) scores.")
for object in objects! {
if let dict = object as? [String: AnyObject] {
if let title = object["Title"] as? String {
self.titles.append(title)
}
if let imgFile = object["imageFile"] as? PFFile {
self.imageFile.append(imgFile)
}
}
self.tableView.reloadData()
}
} else {
// Log details of the failure
println(error)
}
}