Hi I'm creating an app related to iOS. This app display number of people in tableview. Each cell in tableview shows the name of the person and detail of the person also each person have audio file attached. when i select the any cell and hit the shortlist button i want to display this information into another screen and email the selected cell to anyone. So i want to show name, detail, and the audio file into another screen. i am using swift language and Xcode 7. Please help me to find answer.
Please implement TableView Delegate method below, When you select a cell this method will invoke. There you can instantiate new ViewController where you want to display the data.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
First of all you need to find out what cell was selected. Using the didSelectRowAtIndexPath function.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
}
After you have found out what row was selected you can then segue into the next view controller but before this is done you will have to call the prepareForSegue function which allows the variables to be passed into the view controller.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!)
{
}
Use didSelectRowAtIndexPath method current ViewController,
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let sample = storyBoard.instantiateViewControllerWithIdentifier("YourViewControllerIdentifierName") as! ViewControllerB
sample.mainArray = yourArrayName.mutableCopy() as! NSMutableArray
self.navigationController?.pushViewController(sample, animated: true)
}
}
If you send data to Another ViewControllerB declare the variable mainArray,
import UIKit
class ViewControllerB: UIViewController {
var mainArray = NSMutableArray()
}
The above example is one way, you will declare the variable's to pass many data tableview didSelectRowAtIndexPath to Another ViewController,
hope its helpful
Related
What I basically want is I want to press on a row in my TableViewController which then takes, for example, the text that the row has and passes it to a ViewController that is currently not present. Like when you click on a song in the Spotify app and it plays it without presenting anything but the song details are shown in the mini-player.
Does anyone have a clue how to do that?
Well you can do that but you need to initialize your View Controller first for you to access its properties like:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DestinationVc") as? DestinationVc
vc?.text = "TextToBePassed"
}
And there it is without presenting it but I don't get it why you don't want to present or show it but that's how it is done based on your question. Thanks :)
If you have created the UI via XIB or programatically then follow this approach:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let nextVC = NextViewController()
nextVC.text = model?[indexPath.row].text // If you are using model or if you have stored the data in the array then nextVC.text = yourArray[indexPath.row]["text"]
self.navigationController?.pushViewController(nextVC,animated: true)
}
Also, in the NextViewController, you have to add text. Like this:
class NextViewController: UIViewController {
var text = String()
//MARK:- View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
print(text) //This will print the text passed from previous VC
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = NextViewController()
vc.title = "\(Title)"
self.navigationController?.pushViewController(vc,animated: true)
}
Using this method can help you in passing the data to another Controller without using segue.
Assuming this is for iOS as the question doesn't specify.
In the tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) method in your UITableViewDelegate, you can grab the cell's text with
let cell = tableView.cellForRow(at: indexPath)?.textLabel?.text // cell: String?
You can then assign this to a global variable if you wish, or if you maintain a reference to the non-present view controller, you can give it a property to store this text and assign it before you call performSegue(withIdentifier identifier: String, sender: Any?).
I have the following problem:
I am making a Pokédex-like application that displays a list of all 721 Pokémon on the first tab, and another list on the second tab containing My Favorite Pokémon. Essentially, there are two identical ViewControllers connected to my TabBar.
My storyboard is as follows:
So here is the problem:
The TableView on the first (and initial) tab works fine. However, when I load the TableView on the second tab the Pokémon are loaded, but not displayed. I am able to click the TableViewCell and go to the detail page, but the label in the TableViewCell is not showing anything.
This is the code I use for loading Favorites TableView
class FavoritesViewController: BaseViewController,
UITableViewDataSource, UITableViewDelegate {
#IBOutlet var FavoritesListView: UITableView!
var pokemonList: [String] = ["Nothing Here!"]
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("FavoriteCell", forIndexPath: indexPath) as! FavoriteCell
var name = pokemonList[indexPath.row]
capitalizeFirstLetter(&name)
cell.nameLabel.text = name
return cell;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pokemonList.count
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print(pokemonList[indexPath.row])
self.performSegueWithIdentifier("ToPokemonDetail", sender: pokemonList[indexPath.row])
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "ToPokemonDetail"){
let destination = segue.destinationViewController as! PokemonDetailViewController
let thisPokemon = sender as! String
destination.currentPokemon = thisPokemon
}
}
override func viewWillAppear(animated: Bool) {
FavoritesListView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
// Fetch the cached list, getNames returns an array of strings
let list = utility.getNames("Favorites")
pokemonList = list
}
The delegate and the dataSource are set via the storyboard.
The above code works, and shows the Favorites list just fine. The class for the complete Pokédex has a similar construction.
I have tried switching Favorites and Pokédex around, so that it shows the complete Pokémon list on startup. All 721 Pokémon are shown correctly, but then the Favorites are not visible.
What else I have tried:
Checking the Reuse Identifiers, over and over
Referencing outlets should be bound correctly
Calling TableView.reloadData() in the viewDidAppear method
Switching around the tab items
Does anyone have any clue what on earth is going on here?
Feel free to ask any more questions
Edit: this is what happens when I swap the two TabBar Buttons around, no code changes
Pokédex Screen
Favorites Screen
GitHub Project Here
Problem is in storyboard cell label frame. Set constraints of view controller for (Any,Any) Size Class. I can commit the code on github if you can give me write rights on your git. Thanks
Perhaps your table's delegate and dataSource are not set.
table.delegate = self
table.dataSource = self
Of course this is after you add the properties to your view controller
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
Your number of rows is always 0 for that controller,
I looked into your code pokemonList count is always 0 its not updating data in it
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pokemonList.count
}
The big issue is your PokemonDetailViewController is not a UITableViewController. It needs to inherent from UITableViewDataSource, UITableViewDelegate and then be connected to the storyboard view to provide data and formatting for a table.
I want to achieve something similar to the following example image
where I want to present a selected or default category on the first screen
and when it's clicked it moves to the next screen with other category options to choose.
In this example, where it says Entertainment and Project 01 represent different data entities (data store) and it looks like it's using UITableView with each UITableViewCell connected to different data store.
I first want to know if my analysis so far is correct.
In my case, I just need to do that Entertainment part and in the next screen, show all category options like the second screen in the example. And after selection is made, the first screen should reflect the selection from the second screen.
Is UITableView the right choice to show this single field (cell) and segue to another ViewController?
All the demo app examples I see, don't demonstrate the usage of UITableView for this purpose so I'm not sure what is the best option in my case.
Yes UITableView is a good option. Just create a delegate method in "choose category" class. Call the delegate on didSelectRowAtIndexPath method of the UITableView in Category class. Then assign Expense class as the delegate for the category class.
Basically you'll be performing a segue once you click on entertainment. User will be presented with "Choose Category controller" Once the user selects the table row. Delegate will be called. Implement that delegate in the expense class. And in the implementation just reload the table with the new value.
UPDATE:
Your choose category class will be something similar to :
import UIKit
protocol ChooseCategoryControllerDelegate: class {
func categoryController(controller: ChooseCategoryTableViewController, didSelectCategory category: String)
}
class ChooseCategoryTableViewController: UITableViewController {
let categories = ["category1","category2","category3","category4"]
var selectedcategory: String!
weak var delegate: ChooseCategoryControllerDelegate!
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return categories.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("TypeCell", forIndexPath: indexPath)
cell.textLabel?.text = categories[indexPath.row]
return cell
}
// MARK: - Table view delegate
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedcategory = categories[indexPath.row] as? String
delegate.categoryController(self, didSelectCategory: selectedcategory)
}
}
In your expense controller add the following code outside your class declaration:
extension ExpenseController: ChooseCategoryControllerDelegate {
func typesController(controller: ChooseCategoryTableViewController, didSelectCategory category: String) {
let selectedCategory = category
dismissViewControllerAnimated(true, completion: nil)
//update your table category with the new category!!
//reload your table here
}
}
Re-Update:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "CategorySegue" {
let controller = segue.destinationViewController as! ChooseCategoryTableViewController
controller.delegate = self
}
}
Also name your segue as "CategorySegue"
It depends, if the only option is the Entertainment then maybe UITableView is not the best option. Regardless, you can use a UITableView with static cells and a segue from the entertainment cell to the category.
Steps taken:
Created new single view project
Deleted default view controller
Added new Table View Controller
Embedded TVC into a Navigation Controller
Added a child TVC
Added custom class files and associated to each TVC
Created a Show segue from the first TVC to the child
Implemented required methods, #of sections, # of rows, cellForRowAtIndexPath
All of the tutorials I have watched and read online only include the steps I show above, and the segues start working fine. However, in my case I can not get it to work until I add the following:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("detail", sender: tableView)
}
I'm totally fine with implementing the didSelectRowAtIndexPath method if it is required. I'm just wondering if I am missing something, because it seems to work automatically in everything I've seen online.
Thanks in advance!
If you click on the segue (storyboard) and on the side menu you have to assign the text "detail" from
performSegueWithIdentifier("detail", sender: tableView)
on the Identifier field.
Like the image below
Edit:
Try the code above, rembember to change NAME_OF_THE_DETAIL_VIEW_CONTROLLER to your Detail ViewController.
In this code we set i set "self" before the performSegueWithIdentifier. And when the button is clicked you set the segue.destinationViewController to your new ViewController.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("detail", sender: indexPath);
}
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "detail") {
var detailView = segue.destinationViewController as! NAME_OF_THE_DETAIL_VIEW_CONTROLLER
}
}
Thank you all for your contributions. I figured out that the problem was the following was missing from the cellForRowAtIndexPath tableView function.
let cell = self.tableView.dequeueReusableCellWithIdentifier("custom", forIndexPath: indexPath) as! CustomCell
I had this line commented out, mostly because I have no idea what it does. :)
I have a tableView in my application and when a user taps on that cell, I need it to go to another view controller that gives more details about the cell they clicked on. When I try to get the cellForRowAtIndexPath by using
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("You selected cell #\(indexPath.row)!")
}
Nothing is printed to the console so I cant pass that data to another view controller through a segue without knowing that. Is there a reason this would not work?
I am getting the information though this array: var postsArray = [PFObject]() and the table is populated using return postsArray.count
Any help would be greatly appreciated. I may be overlooking it but I am not sure why this would not work as it has worked in other applications of mine.
I have imported delegates as well and have also called table.delegate = self to my viewDidLoad method.
class Profile: UIViewController, UITableViewDelegate, UITableViewDataSource
The full code can be found here: http://pastebin.com/26frZGpa
The line
tableView.delegate = self
as suggested in the very first comment is missing, that's the reason why the delegate method is not called. You can connect the delegate also in Interface Builder.
In your case to perform the segue it's more convenient to connect the segue to the table view cell rather than to the view controller.
The major benefit is that the table view cell is passed as the sender parameter in prepareForSegue and you can get the index path easily with
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let selectedIndexPath = tableView.indexPathForCell(sender as! UITableViewCell)!
}