I am trying to make my tableview cell from viewcontroller 1 change when the user click on a cell from tableview cell from viewcontroller 2. I know that I have to work with the function
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
however, I am not sure how I would accomplish what I wanted.
Here's my code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let indexPath = changeHotelTableView.indexPathForSelectedRow;
let currentCell = changeHotelTableView.cellForRow(at: indexPath!) as! ChangeHotelTableViewCell
var valueToPass = currentCell.textLabel?.text
}
I want to get the valueToPass variable into my cell at another' view controller; say this is called timeViewController with timeTableView and a timeTableViewCell. How will I do this?
Thanks for your help and time in advance
Perhaps you should try with Protocol.
ViewController2:
protocol UserPressTheCell: NSObjectProtocol
{
func didUserPressTheCellWith(indexPath: IndexPath, text: String)
}
class ViewController2: UIViewController
{
//declare delegate
weak var delegate: UserPressTheCell?
....
func tableview(_ tableview: UITableView, didSelectRowAt indexPath: IndexPath)
{
let indexPath = changeHotelTableView.indexPathForSelectedRow;
let currentCell = changeHotelTableView.cellForRow(at: indexPath!) as! ChangeHotelTableViewCell
self.delegate?.didUserPressTheCellWith(indexPath: indexPath, text: currentCell.textLabel?.text)
}
}
Then implement in ViewController1:
class ViewController1: UIViewController, UserPressTheCell
{
#IBOutlet weak var tableview: UITableView!
...
//MARK: UserPressTheCell
func didUserPressTheCellWith(indexPath: IndexPath, text: String)
{
let cell = self.tableView.cellForRow(at: indexPath!) as! "Your VC1's cell"
cell.textLabel?.text = text
}
}
To be sure delegate will not be nil:
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
let vc2 = segue.destination as! ViewController2
vc2.delegate = self
}
or wherever you segue to ViewController2.
Maybe this is the best way to accomplish what you wanted.
Related
please help me to understand why the tableView.indexPathForSelectedRow method returns nil.
I want to make a transfer from Table View Controller to View Controller. I have a segue by a StoryBoard and leadingSwipeActions.
import UIKit
class TableViewController: UITableViewController {
let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return months.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = months[indexPath.row]
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "editItem" {
let path = tableView.indexPathForSelectedRow
print("\(path)") ##// Prints nil.##
}
}
override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let editAction = UIContextualAction(style: .normal, title: "Edit Item") { [self] (action, view, completion) in
performSegue(withIdentifier: "editItem", sender: self)
}
editAction.backgroundColor = .systemOrange
return UISwipeActionsConfiguration(actions: [editAction])
}
}
Leading swipe - and subsequent tap of the action button - does not select the row.
Since the sender parameter of the "prepare for segue" method is defined as Any?, one approach would be to pass the indexPath when you call the segue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "editItem" {
// make sure an Index Path was passed as the sender
if let path = sender as? IndexPath {
print("Index Path: \(path)")
}
}
}
override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
// note: use [weak self] to avoid possible retain cycle
let editAction = UIContextualAction(style: .normal, title: "Edit Item") { [weak self] (action, view, completion) in
guard let self = self else { return }
// pass the path as the sender
self.performSegue(withIdentifier: "editItem", sender: indexPath)
}
editAction.backgroundColor = .systemOrange
return UISwipeActionsConfiguration(actions: [editAction])
}
Edit - in response to comment
The sender: Any? parameter means that sender can be any object. That allows you to differentiate what action or piece of code initiated the segue.
Examples:
self.performSegue(withIdentifier: "editItem", sender: indexPath)
self.performSegue(withIdentifier: "editItem", sender: 1)
self.performSegue(withIdentifier: "editItem", sender: 2)
self.performSegue(withIdentifier: "editItem", sender: "Hello")
self.performSegue(withIdentifier: "editItem", sender: self)
self.performSegue(withIdentifier: "editItem", sender: myButton)
Then, in prepare(...), you can evaluate the sender to decide what to do next.
Quite often, when using table views to "push" to another controller that relates to the tapped cell (a "details" controller, for example), the developer will connect a segue from the cell prototype to Details view controller. Then (if you gave that segue an identifier of "fromCell"), you can do something like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "fromCell" {
if let cell = sender as? UITableViewCell {
if let path = tableView.indexPath(for: cell) {
print("Index Path: \(path)")
// here we might get data for that row/section,
// and pass it to the next controller
}
}
}
}
In your case, we send the indexPath of the cell we just acted on as the sender parameter.
Fairly new to coding and this is my first post here. I added a Prototype Cell to a Table View Cell but when I run the project the cell runs off the page (on the right)? Does anyone have any help they can provide?
This is the ViewController code:
import UIKit
class ConsultationsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
ConsultationFunctions.readConsultations(completion: { [weak self] in
self?.tableView.reloadData()
})
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Data.consultationModels.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! ConsutationsTableViewCell
cell.setup(consultationModel: Data.consultationModels[indexPath.row])
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
}
And this is the TableViewController code:
import UIKit
class ConsutationsTableViewCell: UITableViewCell {
#IBOutlet weak var cardView: UIView!
#IBOutlet weak var titleLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
cardView.layer.shadowOffset = CGSize.zero
cardView.layer.shadowColor = UIColor.systemBlue.cgColor
cardView.layer.cornerRadius = 10
}
func setup(consultationModel: ConsultationModel) {
titleLabel.text = consultationModel.title
}
}
I've tried adjusting the Storyboards Identity, Attributes and Size Inspectors as best I can but just don't understand where I've gone wrong? Any guidance is greatly appreciated
I don't see the interface constraints in your code, so I guess you have them in the Storyboard, or ar least you should.
I suggest you to go through some tutorials or guides to "Add New Constraints" for cardView and titleLabel. Here you have a simple one:
https://www.ralfebert.de/ios-examples/uikit/uitableviewcontroller/custom-cells/
I have a custom UITableViewCell, where i am trying to change the cell.indicatorLabel background color from a func, but i do not know how to access the cell from that func
class mainCell: UITableViewCell {
#IBOutlet weak var barcodeLabel: UILabel!
#IBOutlet weak var indicatorLabel: UILabel!
}
and i have a func called
func scan() {}
my cellForRowAt looks like this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? mainCell
cell?.barcodeLabel.text = barcodeArray[indexPath.row].Barcode
cell?.indicatorLabel.text = barcodeArray[indexPath.row].Indicator
return cell!
}
i like to change the background color of the label from my func, anyone who can help with this?
How to use prepare for segue to transfer the images (tweetImg) and date (dateLbl) from tablecell (mainCell) to the Newviewcontroller when I select the cell? in my case I am using parse.com as my backend to retrieve the images and dates data. I am new to programming would appreciate some help, thank you.
mainVC
import UIKit
class mainVC: UIViewController, UITableViewDataSource, UITableViewDelegate, {
#IBOutlet weak var resultsTable: UITableView!
var resultsStartdateArray = [String]()
var resultsTweetImageFiles = [PFFile?]()
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return resultsTweetImageFiles.count
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 350
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:mainCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! mainCell
cell.dateLbl.text = self.resultsStartdateArray[indexPath.row]
resultsTweetImageFiles[indexPath.row]?.getDataInBackgroundWithBlock({
(imageData:NSData?, error:NSError?) -> Void in
if error == nil {
let image = UIImage(data: imageData!)
cell.tweetImg.image = image
}
})
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("SendDataSegue", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if (segue.identifier == "SendDataSegue")
{
let destination: NewViewController = segue.destinationViewController as! NewViewController
// I believe the missing code should be here
}
}
}
mainCell
import UIKit
class mainCell: UITableViewCell {
#IBOutlet weak var tweetImg: UIImageView!
#IBOutlet weak var dateLbl: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
}
NewViewController
import UIKit
class NewViewController: UIViewController {
#IBOutlet weak var dateLbl: UILabel!
#IBOutlet weak var tweetImg: UIImageView!
var titleString: String!
override func viewDidLoad()
{
super.viewDidLoad()
self.dateLbl.text = self.titleString
}
Bellow i have mentioned a sample template code. organize your code according to bellow mentioned code. important part is select a cell in the prepareForSegue instead of in didSelectRowAtIndexPath. Which is let IndexPath = self.tableView.indexPathForSelectedRow()!
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
//Index path is the selected cell
let IndexPath = self.tableView.indexPathForSelectedRow()!
//Here you can assign your tweetImg and dateLbl
let newViewController = segue.destinationViewController as! NewViewController
newViewController.dateLbl.text = //your date label value
//here assign your image to destination view controller property
}
Delete the method didSelectRowAtIndexPath and connect the segue to the table view cell rather than the view controller.
When a cell is selected it's passed as the sender parameter in the prepareForSegue method.
A side note : Don't perform background tasks in the view – the cellForRowAtIndexPath method – , do it in the model – the items in the data source array – and then call reloadData()
I'm using the Beginning Swift Programming book by AppCoda and I can't seem to figure out what is wrong with this block of code.
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
var restaurantNames = ["Cafe Deadend", "Homei", "Teakha", "CafeLoisl", "Petite Oyster", "For Kee Restaurant", "Po's Atelier", "Bourke Street Bakery", "Haigh’s Chocolate", "Palomino Espresso", "Upstate", "Traif", "Graham Avenue Meats And Deli", "Waffle & Wolf", "Five Leaves", "Cafe Lore", "Confessional", "Barrafina", "Donostia", "Royal Oak", "CASK Pub and Kitchen"]
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return restaurantNames.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->
UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as UITableViewCell
// Configure the cell...
cell.textLabel.text = restaurantNames[indexPath.row]
return cell
}
}
This line is throw a 'AnyObject is not convertible to 'UITableViewCell'
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as UITableViewCell
I'm really new to Swift and iOS programming in general so any help would be appreciated.
You need to change as to as!
var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
Also make sure that you have added a prototype cell to your storyboard with the reusable string name "Cell"
//MARK: Tableview
func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int
{
return tabledata.count
}
func tableView(tableView: UITableView!,
cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
{
let cell:UITableViewCell = UITableViewCell(style:UITableViewCellStyle.Default, reuseIdentifier:"Cell")
cell.textLabel?.text = tabledata[indexPath.row]
return cell
}
I have used this code for tableview....You can change this according to your need.Even I'm new in swift or else I would've correct your code.