Not updating posts Parse Swift - swift

In my parse database, I have some data created within the app, but when I go to the TableViewController showing the posts, it hasn't updated for some off reason. Here is my code (I can provide more info on the parse database if needed to help solve this issue):
import UIKit
import Parse
import ParseUI
class PostsTableViewController: PFQueryTableViewController {
override func queryForTable() -> PFQuery {
let query = PFQuery(className: "Posts")
query.cachePolicy = .CacheElseNetwork
query.orderByDescending("createdAt")
return query
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! PostsTableViewCell
let posterUsernameText = object?.objectForKey("createdBy") as? String
cell.posterUsername.setTitle("\(posterUsernameText)", forState: .Normal)
cell.msgTextView.text = object?.objectForKey("text") as? String
let imageFile = object?.objectForKey("image") as? PFFile
cell.cellImageView.file = imageFile
cell.cellImageView?.loadInBackground()
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row + 1 > self.objects?.count {
return 44
}
let height = super.tableView(tableView, heightForRowAtIndexPath: indexPath)
return height
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row + 1 > self.objects?.count {
self.loadNextPage()
tableView.deselectRowAtIndexPath(indexPath, animated: true)
} else {
self.performSegueWithIdentifier("showDetail", sender: self)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
}
}
}
EDIT: Here is a photo of my database, and a photo of my screen:

I believe you need to reload the data for the PFQueryTableView & you do that with the loadObjects method. As mentioned on Parse's documentation, it clears the table and loads the first page of objects. (You can use loadNextPage to load the next page of objects onto the table view) Here is a link to the PFQueryTableViewController's documentation

Related

Get cell index from tableviewcell

Hey I have this tableview controller that list restaurants from my database. what I want to do is if the cell/row is selected it opens a more detail page about the restaurant. for some reason I can't retrieve the index or its not going to the func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) to give me index here is what I have:
class HomeTableViewController: UITableViewController{
var restaurantArray = [Restaurant]()
var resTransfer: Restaurant?
var resName: String?
var dataBaseRef: FIRDatabaseReference! {
return FIRDatabase.database().reference()
}
override func viewDidLoad() {
super.viewDidLoad()
title = "Home"
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Main Menu", style: .plain, target: self, action: #selector(SSASideMenu.presentLeftMenuViewController))
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
fetchRestaurants()
}
func fetchRestaurants(){
FIRDatabase.database().reference().child("AthensRestaurants/Restaurants").observe(.value, with: { (snapshot) in
var results = [Restaurant]()
for res in snapshot.children{
let res = Restaurant(snapshot: res as! FIRDataSnapshot)
results.append(res)
}
self.restaurantArray = results.sorted(by: { (u1, u2) -> Bool in
u1.name < u2.name
})
self.tableView.reloadData()
}) { (error) in
print(error.localizedDescription)
}
}
// MARK: - Table view data source
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return restaurantArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "restaurantsCell", for: indexPath) as! RestaurantsTableViewCell
// Configure the cell...
cell.configureCell(res: restaurantArray[indexPath.row])
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("Row \(indexPath.row)selected")
resTransfer = restaurantArray[indexPath.row]
resName = restaurantArray[indexPath.row].name
print(resName as Any)
performSegue(withIdentifier: "RestaurantDetailView", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "RestaurantDetailView") {
let vc = segue.destination as! RestaurantDetailViewController
vc.resNam = restaurantArray.first?.name //instead of first should be index of cell!
print(vc.resNam! as String)
}
}
}
I am doing it like this, without segue:
func showRestaurantViewControllerWith(_ id: String) {
let storyBoard = UIStoryboard(name: "RestaurantCard", bundle: nil)
let destinationVC = storyBoard.instantiateViewController(withIdentifier: "RestaurantCard") as! RestaurantCardViewController
destinationVC.restaurant.id = id
self.navigationController?.pushViewController(destinationVC, animated: true)
}
and
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.showRestaurantViewControllerWith(self.allRestaurants[indexPath.row].id)
}
You have to use this function to fetch the index
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
print(indexPath.row)
}
It will give you the index.
First of all your code is obviously Swift 3 so the signature of didSelectRowAt is wrong.
Another solution is to pass the indexpath as sender
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Row \(indexPath.row)selected")
performSegue(withIdentifier: "RestaurantDetailView", sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "RestaurantDetailView" {
let indexPath = sender as! IndexPath
let restaurant = restaurantArray[indexPath.row]
let resName = restaurant.name
print(resName!)
let vc = segue.destination as! RestaurantDetailViewController
vc.resNam = resName
}
}
or still easier to connect the segue to the table view cell. Then you can delete didSelectRow... because prepare(for is called directly and the cell is passed as the sender parameter.
PS: Why is the property name optional? In real life have you ever heard about a restaurant without a name?

Passing Data between TableView in Swift

I have two tableView running in my project.I am trying to pass(copy) my first tableViewcell data to second tableView.I using tableView row action method to pass data.My partial code below...
First VC:
var tableView: UITableView!
var DataArray = ["Bus","Helicopter","Truck","Boat","Bicycle","Motorcycle","Plane","Train","Car","S cooter","Caravan"]
var sendSelectedData = NSString()
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let copyAction = UITableViewRowAction(style: UITableViewRowActionStyle.normal, title: "Pass Data") { (UITableViewRowAction, NSIndexPath) -> Void in
print("Button Pressed") // Xcode Console prints **Button Pressed** when swipe action performed.
self.performSegue(withIdentifier: "send", sender: self)
}
return [copyAction]
}
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
self.performSegue(withIdentifier: "send", sender: self)
// segue.destination as! tableController
let indexPath = tableView.indexPathForSelectedRow
let currentCell = tableView.cellForRow(at: indexPath!)!
self.sendSelectedData = (currentCell.textLabel?.text)! as String as NSString
let viewController = segue.destination as! tableController
viewController.labelcell = ([self.sendSelectedData as String])
print(self.sendSelectedData) // no result
}
Second VC:
var labelcell = [String]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: textCellIdentifier, for: indexPath as IndexPath) as UITableViewCell
cell.textLabel?.text = labelcell[indexPath.row] as? String
tableView.reloadData()
return cell
}
Above code looks like passing data to my second VC(segue).But, I am only getting a empty tableview..
Okay after testing it, it turns out, that you're using an incorrect prepareForSegue function. You are not using "prepareForSegue", you are creating a function called prepareForSegue - since the syntax has changed in Swift 3. This one will get called and you can pass data.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "send" {
let selectedIndex = sender as! NSIndexPath
let currentCell = tableView.cellForRow(at: selectedIndex as IndexPath)! as! Cell
self.sendSelectedData = (currentCell.label?.text)! as String as NSString
print(self.sendSelectedData) // till here it worked for me - it is filled with my label.text
// I don't know what this is "viewController.labelcell", so you have to to know how to go on from here on
viewController.labelcell = ([self.sendSelectedData as String])
}
}
Also you need to pass the indexPath:
self.performSegue(withIdentifier: "send", sender: indexPath)
Exactly like this:
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let copyAction = UITableViewRowAction(style: UITableViewRowActionStyle.normal, title: "Pass Data") { (UITableViewRowAction, NSIndexPath) -> Void in
print("editActionsForRowAt called") // Xcode Console prints **Button Pressed** when swipe action performed.
self.performSegue(withIdentifier: "send", sender: indexPath)
}
return [copyAction]
}
This worked in my testing project.
Also beware: Cell is a custom subclass of UITableViewCell I have created and label is an UIOutlet of a label element for my test project.

Transfer TableviewCell to AnotherTableView in swift

I have two tableView (FavouriteViewController and MainViewController) controllers in my project and the ViewController connected through segue with button. I have some data running in my MainViewController and the FavouriteViewController basically with no data in it.I am trying to transfer tableViewCell when the cell clicked from MainViewController to favouriteViewController using tableViewCell swipe action method or any another suggeste method.
my codes as below.
My MainViewController
var arrays = ["Alpha","Beta","Gamma","Phill","Below","Above","Clean",]
var sendSelectedData = NSString()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
title = "FavTV"
let titlebutton: UIButton = UIButton(frame: CGRectMake(0, 0, 100, 32))
titlebutton.setTitle("Quote", forState: UIControlState.Normal)
titlebutton.titleLabel?.font = UIFont(name: "PartyLetPlain", size: 35)
titlebutton.setTitleColor(UIColor.redColor(), forState: UIControlState.Normal)
titlebutton.addTarget(self, action: "titlePresed", forControlEvents: UIControlEvents.TouchUpInside)
self.navigationItem.titleView = titlebutton
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell1")
self.tableView.reloadData()
}
func titlePressed() {
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
self.performSegueWithIdentifier("ShowDetails", sender: nil)
segue.destinationViewController as! favTableViewController
}
self.performSegueWithIdentifier("ShowDetails", sender: nil)
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = tableView.indexPathForSelectedRow!
let currentCell = tableView.cellForRowAtIndexPath(indexPath) as UITableViewCell!
sendSelectedData = (currentCell.textLabel?.text)! as String
//self.arrays.append(String(indexPath.row)
// performSegueWithIdentifier("ShowDetails", sender: self)
}
override func tableView(tableView: UITableView,commitEditingStyle editingStyle: UITableViewCellEditingStyle,forRowAtIndexPath indexPath: NSIndexPath) {
}
///////////////////////
override func tableView(tableView: UITableView,commitEditingStyle editingStyle: UITableViewCellEditingStyle,forRowAtIndexPath indexPath: NSIndexPath) {
switch editingStyle {
case .Delete:
// remove the deleted item from the model
self.arrays.removeAtIndex(indexPath.row)
performSegueWithIdentifier("ShowDetails", sender: self)
tableView.reloadData()
default:
return
}
}
/////////////////////
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "ShowDetails") {
// initialize new view controller and cast it as your view controller
let viewController = segue.destinationViewController as! favTableViewController
// your new view controller should have property that will store passed value
viewController.arrayx = [sendSelectedData as String]
///////////////////////
self.arrays.append(sendSelectedData as String)
/////////////////////
}
}
My FavouriteTableView:
var arrayx = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
title = "Fav"
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayx.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = arrayx[indexPath.row] as? String
return cell
}
}
Above code works in a simple way when i press the cell from MainViewController and then when the titlePressed() button pressed. it passing the pressed cell data to FavouriteTableView....
I need some suggetion how to transfer cell to my FavouriteTableView permanently.I am not sure about my logic is right. Please some one point me the right direction.
Thanks in Advance...
What shows up in a table is driven by :
var arrayx = [] // <-- CHANGE THE CONTENTS OF THIS ARRAY
Change the data in that array and then reload the table.
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
Here is your function that gets the data and puts it into the cells.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
// arrayx is the data that drives the table.
// changing the data in arrayx will cause the table to show different data.
// **********************************************
// ** The table will show whatever is in arrayx
// ** therefore, if you change arrayx then table
// ** will have that new data.
// **********************************************
cell.textLabel?.text = arrayx[indexPath.row] as? String
// **********************************************
return cell
}

Segue not sending correct cell info in Swift

I have a tableView that triggers a segue to a detail view when a cell is pressed. The table contains a list of users that the currentUser is friends with. Pressing the cell loads the view for that user (name, profile, etc). It's a very simple app I'm creating to learn how to program.
The problem is that when I press on a cell, it's always loading the user info for the last user in the table (and also happens to be the most recent "friend" that the user made). I have a feeling that the issue is with an if statement I have in the tableView function:
extension MatchesViewController: UITableViewDataSource
{
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return numberOfMatches
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("MatchCell", forIndexPath: indexPath)
if PFUser.currentUser()!.objectId == self.user1.objectId{
let user = matchesResults[indexPath.row]["user2"] as! PFUser
cell.textLabel?.text = user["first_name"] as! String
self.viewUser = user
}
if PFUser.currentUser()!.objectId == self.user2.objectId{
let user = matchesResults[indexPath.row]["user1"] as! PFUser
cell.textLabel?.text = user["first_name"] as! String
self.viewUser = user
}
return cell
}
}
Here's the segue code, but I don't think there is an issue with it (although I could be wrong):
extension MatchesViewController: UITableViewDelegate
{
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
self.performSegueWithIdentifier("UserSegue", sender: "viewUser")
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "UserSegue") {
let destinationVC = segue.destinationViewController as! UserViewController
destinationVC.user = self.viewUser
}
}
}
Any ideas? If there is an issue with my tableView If statement, how can I fix it?
Thanks!
You can get the user object by indexPath, than pass it through the sender parameter of the performSegueWithIdentifier method
extension MatchesViewController: UITableViewDelegate
{
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let user:PFUser?
if PFUser.currentUser()!.objectId == self.user1.objectId{
user = matchesResults[indexPath.row]["user2"] as! PFUser
}
if PFUser.currentUser()!.objectId == self.user2.objectId{
user = matchesResults[indexPath.row]["user1"] as! PFUser
}
self.performSegueWithIdentifier("UserSegue", sender: user)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// sender is the user object
if (segue.identifier == "UserSegue") {
let destinationVC = segue.destinationViewController as! UserViewController
destinationVC.user = sender // maybe you need cast sender to UserObject
}
}
}

Delete row in TableView and remove the core data - iOS / Swift

I am having an issue with my swift app. I am trying to implement the swipe feature that will prompt the user with the "DELETE" option. As of right now my code only allows me to swipe but the delete button is not being generated. I am currently using Xcode 6.3.2 as well.
Thank you in advance!
import UIKit // apples code for all UI related code
import AVFoundation // apple's code for audio and video
import CoreData
class SoundListViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var audioPlayer = AVAudioPlayer() // creating an audio player property as the variable audioplayer
var sounds : [Sound] = [] // creating an array to hold all sounds, in swift you need to tell the array what it will be holding, this is done by ": [Sound]" this tells the array that it will contain Sound objects
override func viewDidLoad() {
super.viewDidLoad()
// comment
self.tableView.dataSource = self // added to make the Table view work
self.tableView.delegate = self // added to make the Table view work
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// comment
var context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext!
var request = NSFetchRequest(entityName: "Sound") // allows to go get all the objects stored in core data
self.sounds = context.executeFetchRequest(request, error: nil)! as! [Sound]
self.tableView.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.sounds.count // # of rows we want the table view to have based on the contents of sounds array
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var sound = self.sounds[indexPath.row] // searches the index path of each row from the array of sounds and stores to the varibale sounds once it has the correct object
var cell = UITableViewCell() // each cell on the table
cell.textLabel!.text = sound.name // adds the correct name from each object to the correct row
if(indexPath.row % 2 == 0){ // adding color to each cell
cell.backgroundColor = UIColor.lightGrayColor()
cell.textLabel?.textColor = UIColor.whiteColor()
}else if (indexPath.row % 2 != 0){
cell.backgroundColor = UIColor.whiteColor()
}
return cell // printing the new data into each cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var sound = self.sounds[indexPath.row]
var baseString : String = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] as! String
var pathComponents = [baseString, sound.url]
var audioNSURL = NSURL.fileURLWithPathComponents(pathComponents)
self.audioPlayer = AVAudioPlayer(contentsOfURL: audioNSURL, error: nil) // play command while asking for where the audio lives
self.audioPlayer.play() // play audio command on click
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete){
sounds.removeAtIndex(indexPath.row) // array of objects that we are selecting
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation:.Fade)
self.tableView.reloadData()// updated table view
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var nextViewController = segue.destinationViewController as! newSoundViewContoller
nextViewController.soundListViewController = self
}
}
I can't find your issues specifically but. Here is some code that worked for me. Let me know if it works for you.
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.tableView.dataSource = self
self.tableView.delegate = self
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell()
cell.textLabel!.text = "Delete me!"
return cell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete){
println("DELETED")
}
}
}
SOLVED
The issue with my delete was not the issue. (NOTE: you do not need the "tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation:.Fade)" line in your delete function.)
The issue I was originally having was that the slide would work but the user would not be prompt with the delete.
Make sure you check your constraints with your tableView. Also make sure you uncheck the "Constraint to margins" option.