Custom UITableViewCells repeating when navigating to viewcontroller - swift

I am making a running app, and would like the user to see the races/marathons in their city. When clicking on the cell the user is navigated to a new view controller with details of the marathon. But upon pressing the back button to go back to the table the cells repeat. for example, if scrolling on the table it will display cell 1, cell 2,cell 3, cell 4,cell 1, cell 2,cell 3, cell 4 and will repeat more every time I navigate to the view controller with the table.
The code for the table is:
//MARK: TableView
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return exhibitions.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let singleCell: marathonTableViewCell = tableView.dequeueReusableCellWithIdentifier("marathonCell") as! marathonTableViewCell
singleCell.marathonName.text = exhibitions[indexPath.row]
singleCell.entryNumber.text = "\(entryNumber[indexPath.row])"
singleCell.entries.text = "\(entires[indexPath.row])"
return singleCell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("marathonDetail", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "marathonCardDetail"){
var upcoming: marathonDetailViewController = segue.destinationViewController as! marathonDetailViewController
let indexPath = self.marathonsTableView.indexPathForSelectedRow!
let currentCell = marathonsTableView.cellForRowAtIndexPath(indexPath) as! marathonTableViewCell
let marathonEvents = currentCell.marathonName.text
upcoming.nameMarathon = marathonEvents
self.marathonsTableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
I am using swift, Xcode 7, and Parse as my backend.

I think u have to init ur array before update tableview.
When u click back button, tableview may refresh.
So make some code that makes ur array new, and then call tableview.reloadData()

Related

How to make a push segue when a specific UITableViewCell is selected

I am working on my first iOS app and new student to swift.
Everything is working however I am having trouble figuring out how to segue from a specific cell to a third view controller. I have a IOS UITableView with three sections and a total of (44) cells. All cells when tapped segue to one DetailVC titled: showProductDetai which is fine. The problem that I am having is that I need to have only (1) particular cell in section 0 row 5 in the UITableView to go to its own ViewController in which I titled: second view controller instead of the normal showProductDetail VC. Is there an intelligent way to make the specific cell in section 0 row 5 of the tableView go to second view controller when selected?
Here is my current code that is working. How would I code to make the changes?
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProductCell", for: indexPath) as! ProductTableViewCell
// Configure the cell...
let productLine = productLines[indexPath.section]
let products = productLine.products
let product = products[indexPath.row]
cell.product = product
return cell
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let productLine = productLines[section]
return productLine.name
}
// Mark: UITableViewDelegate
var selectedProduct: Product?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let productLine = productLines[indexPath.section]
let product = productLine.products[indexPath.row]
selectedProduct = product
performSegue(withIdentifier: "ShowProductDetail", sender: nil)
}
// Mark: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "ShowProductDetail" {
let DetailVC = segue.destination as! DetailViewController
DetailVC.product = selectedProduct
}
}
see what I did here? You can use the indexPath parameter to get the section & row the user touched, and then you can set up your programmatic segue.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
if ((indexPath.section == 0) && (indexPath.row == 5)) {
performSegue(withIdentifier: "GoToSecondViewController", sender: nil)
} else {
let productLine = productLines[indexPath.section]
let product = productLine.products[indexPath.row]
selectedProduct = product
performSegue(withIdentifier: "ShowProductDetail", sender: nil)
}
}
Write a segue code for the desired section and row:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 0 && indexPath.row == 5 {
//Perform Segue
} else {
//Rest of the functionality
}
}
Make sure you have connected proper Sugues and given proper identifiers in Storyboard.
You don't need to write prepare Segue method

How to know which cell was tapped in tableView using Swift

I am using a tableView to display a list of names. When the user taps on one of the cells, a popup should come up showing more detail. I am using this function to check what cell the user has tapped.
var selectedCell: Int?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("This cell from the chat list was selected: \(indexPath.row)")
selectedCell = indexPath.row
}
Unfortunately, it seems to give give back random numbers between 0 and 2 (I currently have three cells that are displayed).
Do you know how I could know which cell was tapped?
Thank you in advance.
EDIT:
I understood what is falsing my results.
I am using this function to push which cell is selected to another view controller (named ConversationViewcontroller). But, the segue fonction is called before the tableView function, and so the segue pushes the previously selected cell. How could I correct this?
Here is the code for my segue:
//SEGUE: Cell was selected: pass chatID
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "OpenChat" {
if let toViewController = segue.destination as? ConversationViewController {
toViewController.chatIdentifier = selectedCell
}
}
}
Thanks again.
try this
var selectedCell: IndexPath
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("This cell from the chat list was selected: \(indexPath.row)")
selectedCell = indexPath
}
if you want use IndexPath
self.selectedCell?.row

SWIFT if statement and segue

I have a problem with if statement and segue
can I make a connection between them !
I have an array of these states ["Florida","NY"]()
my idea, for example, if I clicked "Florida"<(this is "string") on table view
I want the segue moves me from this table view to another table view
and if I clicked "NewYork" on tableView I want the segue moves me from this table view to another that has information about NY
thanks
You could do something like this:
class SelectCityViewController : UITableViewController {
// store a reference to use in transition
var selectedCity : String?
let cities : [String] = ["New York", "San Francisco", "Los Angeles"]
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = //TODO: your implementation here
cell.textLabel?.text = cities[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.selectedCity = cities[indexPath.row]
performSegueWithIdentifier("YOUR_SEGUE_IDENTIFIER", nil)
}
override func tableView(tableView: UITableView, numberOfItemsInSection section: Int) -> Int {
return self.cities.count
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let vc = segue.destinationViewController as? CityDetailViewController {
vc.selectedCity = self.selectedCity!
}
}
}
Then your second view controller would have a variable with your selected city stored in it so you could setup your content accordingly
class SelectedCityDetailViewController : UITableViewController {
// Set during the segue
var selectedCity : String!
// The rest of your methods
}
you can do something like this in didSelectRowAtIndexPath.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let currentCell = tableView.cellForRowAtIndexPath(indexPath)! as UITableViewCell
if let text = currentCell.textLabel?.text {
if text == "Florida"{
// segue tableview controller
} else if text == "NY" {
//another segue
}
}
}
Take a viewController and add a tableView. Add two another view controllers, one for the NY info and the other containing one more uiTableView. Create two segues from main controller to the other two. Name the segues so that you can refer to them in the code. In didSelectRowAtIndexPath add the following Code:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let currentCell = tableView.cellForRowAtIndexPath(indexPath)! as UITableViewCell
if indexPath.row == 0{
self.performSegueWithIdentifier("florida", sender: nil)
}else if indexPath.row == 1{
self.performSegueWithIdentifier("ny", sender: nil)
}
}
Please check this Link. I have created a demo project for you. I think you are a starter to the iOS development. Carry On!! :)

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

Get data from a cell with "willSelectRowAtIndexPath" in Swift2

I'm trying since two weeks with the help of many Tutorials to get and segue data from a TableView cell. But it seems it is impossible to do that in XCode. It is only possible to get the selectedRow of a cell, but I cannot read out the Text labels of a selected cell.
If a user selects a Cell I want to segue the value of a label in the selected cell to a new View Controller.
I can only submit the selected row to a new View Controller but not the value of a label in this selected cell.
func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
row = indexPath.row // here is the row the user has selcted
labelStringOfselectedCell = "??????" // how to retrieve data from a label in the cell?
return indexPath
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let DestViewController : ViewControllerDetail = segue.destinationViewController as! ViewControllerDetail
DestViewController.seguedData = labelStringOfselectedCell
}
If you really wanted to do something like that, you can do something like:
func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
let cell = tableView.cellForRowAtIndexPath(indexPath) // do not confuse this with the similarly named `tableView:cellForRowAtIndexPath:` method that you've implemented
let string = cell?.textLabel?.text
return indexPath
}
Clearly it depends upon whether you're custom cell subclass and what the label was, but that illustrates the basic idea.
Having said that, you should not do this. Your app should be following Model-View-Controller (MVC) programming paradigm. When determining what data to pass to the next scene, you should go back to the original model you used when originally populating the table, not referring to some control in the table.
For example, let's imagine that you populated the original cell by retrieving data from the objects model:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
let object = objects[indexPath.row]
cell.textLabel?.text = object.name
return cell
}
Then you would just implement a prepareForSegue that retrieves the data from objects also (and you don't have to implement willSelectRowAtIndexPath at all):
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let destination = segue.destinationViewController as? ViewControllerDetail {
let object = objects[tableView.indexPathForSelectedRow!.row]
destination.seguedData = object.name
}
}
Clearly, this will change depending upon what your model was and how you originally populated the cell, but hopefully it illustrates the basic idea.