Passing Data between TableView in Swift - 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.

Related

cast UIButton from cell to run a query and send results to another cell

i'm querying data from a VC and sending the output to another VC that has a TableViewCell. with the results in the cell, i'm trying to run another query to Firebase and display the results in another VC that has a custom prototype cell. i'm able to manually run the queries in both instances, my issue(confusion) is how to call the IBAction button to run the query. I dont know how to cast the cell to run the query and performSegue to the thirdVC
mainVC
#IBAction func getDataPressed(_ sender: Any) {
query......
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "cell1" {
let vc = segue.destination as! secondVC
vc.data = data
self.performSegue(withIdentifier: "cell1", sender: self)
}
}
secondVC
func tableView(_ tableView: UITableView, numberOfRowsInSection section:
Int) -> Int {
return info.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier:
"secondVcCell", for: indexPath)
as? secondVcCell {
cell.configureCell(inf: info[indexPath.row])
return cell
}
return UITableViewCell()
CustomCellDelegate
protocol CustomCellDelegate {
func callSegueFromcell(_ sender: Any?)
secondVcCell
var delegate: CustomeCellDelegate?
#IBOutlet weak var cellBtn: UIButton
#IBAction func getDataPressed2(_ sender: Any) {
query ........
}
if(self.delegate !=nil)
self.delegate.callSegueFromcell(Any)
thirdVC
func tableView(_ tableView: UITableView, numberOfRowsInSection section:
Int) -> Int {
return info2.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "thirdVcCell",
for: indexPath)
as? ThirdVcCell {
cell.configureCell(inf1: info2[indexPath.row])
return cell
}
return UITableViewCell()
for the query, just call the function for querying in the IBAction button by typing the function within the range.
for the second cast if you are pulling from firebase then you will need to change your code to include firebase DataBase or Firestore, if you are taking it manually then you need to do the same as the first cast but make sure the indexPath is correct

How to create segue from Detail disclosure of static cell from xib file

Have some question that I can't figure out. I have single static cell in xib file and I want to make segue from detail disclosure accessory of that cell to other view controller.
Guess that I have to use this method:
func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
self.performSegue(withIdentifier: "SegueID", sender: self) // #ERROR
}
But I have an error:
Could not cast value of type 'Lists.ListViewController'
(0x104c0e7b8) to 'UITableViewCell' (0x106875bf8).
How can I create this segue correctly?
If you want to access the cell in prepareForSegue you can try like this way.
func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
//Pass the indexPath as sender
self.performSegue(withIdentifier: "SegueID", sender: indexPath)
}
Now access that indexPath in prepareForSegue.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "SegueID" {
let nextVC = segue.destination as! DestinationVC
if let indexPath = sender as? IndexPath,
let cell = self.tableView.cellForRow(at:indexPath) as? CustomCell {
//access your cell here
}
}
}

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?

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
}
}
}