import UIKit
class TableViewControllerOne: UITableViewController {
let musicArray = ["Old Town Road", "Starboy"]
var songName = ""
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSections(in 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 musicArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath)
cell.textLabel!.text = musicArray[indexPath.row]
//here is the problem
songName = cell.textLabel!.text!
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var vc = segue.destination as! ViewControllerOne
vc.songFinalName = self.songName
}
}
So I am doing music player App, but I don't know how to play current song. I have all songs in a row(identifier is MyCell). When I click on the cell named for example ,,Starboy" it should get that name and pass the data to the other VC and there play it, but always it only plays the latest thing that is in the raw, so for example there are 3 songs: Old Town Road, Starboy, Hello and it can play only the latest so in this example it is Hello. Can someone help me please? Thank you for reading.
You need to implement tableview's delegate method didSelectRowAt which will update the songName property whenever a user taps on any row of table view
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
songName = musicArray[indexPath.row]
}
Moreover, remove songName = cell.textLabel!.text! from cellForRowAt: indexPath method
Related
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
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
There is a tableview cell and there is a more button which is located on the tableview not in the cell so I want that when the project run it show only five user data in the tableview cell and other user data is show when the user click on the more button(which is located out side the cell) how do I achieved this?
Thanks for help
You can find the prototype cell image
//Mark:TableViewDelegate
extension MembersViewController:UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return imgarray.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tblView.dequeueReusableCell(withIdentifier: "membTableCell", for: indexPath) as! membTableCell
cell.profiletabImg.image = imgarray[indexPath.row]
cell.namelbl.text = names[indexPath.row]
cell.positionlbl.text = "Ceo of code with color"
return cell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 40
}
#IBAction func morebutton(sender:UIButton){
}
}
The tableview expands automatically if you add data to the array and call the tableview.reloadData() function.
From the Apple's Doc -
"Call this method to reload all the data that is used to construct the table, including cells, section headers and footers, index arrays, and so on. For efficiency, the table view redisplays only those rows that are visible. It adjusts offsets if the table shrinks as a result of the reload. The table view’s delegate or data source calls this method when it wants the table view to completely reload its data. It should not be called in the methods that insert or delete rows, especially within an animation block implemented with calls to beginUpdates() and endUpdates()."
#IBAction func moreBtnPressed(_ sender: Any) {
tableviewArray.append("Append your array with remaining items")
tableview.reloadData()
}
Return 5 in numberOfRowsInSection method if more button is not tapped.
When more button is tapped reload the tableview and return imgarray.count in numberOfRowsInSection method.
class TableViewController: UITableViewController {
var dataArr = [String]()
var expanded = false
override func viewDidLoad() {
super.viewDidLoad()
dataArr = (1..<25).map({ String($0) })
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "\(dataArr.count - 5) more", style: .plain, target: self, action: #selector(morebutton(_:)))
}
#objc func morebutton(_ sender: UIBarButtonItem) {
self.navigationItem.rightBarButtonItem = nil
expanded = true
tableView.reloadData()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if !expanded && !dataArr.isEmpty {
return 5
} else {
return dataArr.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier") ?? UITableViewCell(style: .default, reuseIdentifier: "reuseIdentifier")
cell.textLabel?.text = dataArr[indexPath.row]
return cell
}
}
I have two view controller with tableviewcell and in both of them I can add items.
What I want to implement is that when I add items in the first tableviewcell lets say I add (item one , item two) and press on (item one).
I want to sugue to the second tableviewcell and add data.
BUT I want the data in the second tableviewcell to save separately,
that means, now if I press on (item one) I should see the data that I added
but if I press on (item two) it should be empty and I can add data later.
I have saved the data for the two tableviewcell in coredata.
I don't use segues or coredata in this solution, but the solution will fix what you need to some extent at least.
class vc1: UIViewController, UITableViewDelegate, UITableViewDataSource {
let tableView = UITableView()
let options: [Int] = [1,2]
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return options.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = vc2()
//Not sure where to put the setup to be honest
//option 1:
vc.setupTableView(forCell: indexPath.item)
present(vc, animated: true) {
//option 2:
vc.setupTableView(forCell: indexPath.item)
}
}
}
class vc2: UIViewController, UITableViewDelegate, UITableViewDataSource {
let tableView = UITableView()
var selectedCell: Int!
//Having an nested array in an array will solve this custom "page" you are looking for
let results: [[String]] = [["test1", "test2"], ["test3", "test4"]]
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func setupTableView(forCell cell: Int) {
selectedCell = cell
tableView.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return results[selectedCell].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel = results[selectedCell][indexPath.item]
return UITableViewCell()
}
}
The other errors have been fixed, but now I am getting another unresolved identifier at "let secondViewController = segue.destination as! SecondViewController"
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "meunSegue", sender: self)
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
}
}
let secondViewController = segue.destination as! SecondViewController
class SecondViewController: UIViewController {
var recievedData = ""
override func viewDidLoad() {
super.viewDidLoad()
print(recievedData)
}
}
}
In numberOfRowsInSection you need to return the number of rows count, currently you are returning numberRowsOfInSection but there is no declaration of numberRowsOfInSection in your ViewController. So return the number of rows count that you want with your tableView.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
Also with cellForRowAt you are returning UITableViewCell() empty cell so you can't see in tableView instead of that dequeue the cell and then set the label text that you want and return the cell.
Note: In your code you have added didSelectRowAt and prepareForSegue method outside your class, you need to add that inside your class.