I try to get the jobImage shown on the DetailViewController when I press on the Cell, but the imageView on the DetailVC is empty...
Please make sure few things,
In JobDetailViewController the struct has the image in jobImage variable
The IBOutlet jobImageView is connected in UI
You can use the delegate method didSelectRowAt that is in UITableViewDelegate.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let job = jobs[indexPath.row] // get the Object
let image = job.jobImage // get the Image
let destinationVC = DetailVC()
destinationVC.jobDetails = JobDetailViewController.JobDetails(jobDetail: jobs[indexPath.row].text, userName: jobs[indexPath.row].addedByUser!, jobImage: jobs[indexPath.row].jobImage)
destinationVC.performSegueWithIdentifier("toDetails", sender: self)
}
Read more about UITableViewDelegate here.
Related
I have a table view, and when I select an item I enter a screen to where I can edit the object, and then it will bring the item back into the ViewController where the array lives. I can't seem to get the index of the selected item in the array. I would imagine I the index lives in this function as I call the segue and then send over the object for editing.
Function:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "goToEditArea", sender: self)
}
Here is where I get the array to send over.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as! addArea
if let selectedIndexPath = areaTableView.indexPathForSelectedRow {
// Send over the area to update
vc.area = areaArray[selectedIndexPath.row]
}
}
Basically I just need the integer value for the object so I can save in the correct slot.
In your tableView(_:didSelectRowAt:) pass indexPath.row to the performSegue(withIdentifier:sender:):
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "goToEditArea", sender: indexPath.row)
}
Then, you can get that value later in prepare(for:sender:):
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as! addArea
if let row = sender as? Int {
vc.area = areaArray[row]
}
}
I'm using a UITabBarController to create a contact list, but when I'm trying to save the array to load the data when I restart the app is giving me problems where the data isn't displayed. I'm using UserDefaults to save the data and the restore when the app is restarted.
In this code I sent data from a textfield to the array named list.
import UIKit
class NewContactoViewController: UIViewController {
#IBOutlet weak var input: UITextField!
#IBAction func add(_ sender: Any) {
if (input.text != "") {
list.append(input.text!)
UserDefaults.standard.set(list, forKey: "SavedValue")
input.text = ""
}
}
}
In this code I'm printing the data in a table, and trying to save it with user defaults.
import UIKit
var list = [String]()
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let x = UserDefaults.standard.object(forKey: "SavedValue") as? String {
return (x.count)
}
return (0)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
if let x = UserDefaults.standard.dictionary(forKey: "SavedValue") as? String {
cell.textLabel?.text = [x[indexPath.row]]
}
return(cell)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCellEditingStyle.delete {
list.remove(at: indexPath.row)
myTableView.reloadData()
}
}
override func viewDidAppear(_ animated: Bool) {
myTableView.reloadData()
}
#IBOutlet weak var myTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
}
You are saving an array of strings but you are reading a single string (or even a dictionary) which obviously cannot work. There is a dedicated method stringArray(forKey to read a string array.
Apart from the issue never read from UserDefaults to populate the data source in the table view data source and delegate methods, do it in viewDidLoad or viewWillAppear for example
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let savedArray = UserDefaults.standard.stringArray(forKey: "SavedValue") {
list = savedArray
}
myTableView.reloadData()
}
Put the data source array in the view controller. A global variable as data source is very bad programming habit.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var list = [String]()
...
In numberOfRowsInSection return the number of items in list and return is not a function, there are no parentheses
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.count
}
Same in cellForRow. Get the item from list and use reusable cells and again, return is not a function.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = list[indexPath.row]
return cell
}
Note :
Consider that UserDefaults is the wrong place to share data between view controllers. Use segues, callbacks or protocol / delegate.
I am trying to create a custom table view but stumble upon every code. As of right now, I have this below. It's messy and probably wrong but could someone help?
Also, I keep getting an error code
unexpectedly found nil while unwrapping optional value
import UIKit
class tableOutlineViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var names = ["Max", "Bill", "Reagan", "Mikayla", "Jessie", "Sierra", "Jeff", "Erik", "Landon"]
var numbers = ["35", "33", "29", "27", "25", "23", "19", "15", "11"]
var photo = [UIImage(named: "Person1"), UIImage(named: "Person2"), UIImage(named: "Groceries"), UIImage(named: "Person3"), UIImage(named: "Person4"), UIImage(named: "Person5"), UIImage(named: "Person6"), UIImage(named: "Person7")]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "CustomCell") as! CustomCell
cell.images.image = photo[indexPath.row]
cell.name.text = names[indexPath.row]
cell.number.text = numbers[indexPath.row]
return cell
}
}
The error is at the following line because it's unable to force unwrap CustomCell:
let cell = self.tableView.dequeueReusableCell(withIdentifier: "CustomCell") as! CustomCell
As you may be using Nib for your custom cell, you should firstly get it registered in viewDidLoad.
let nib = UINib(nibName: YOUR_CUSTOM_CELL_NIB_NAME, bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "CustomCell")
Seems like you forgot to define identifier(CustomCell) inside attribute inspector of your Xib file of custom cell. So you when you are doing force unwrapped you are getting nil. Also avoid doing force unwrapped to avoid the crash. Have refactored the code :-
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = self.tableView.dequeueReusableCell(withIdentifier: "CustomCell") as? CustomCell else {return UITableViewCell()}
cell.images.image = photo[indexPath.row]
cell.name.text = names[indexPath.row]
cell.number.text = numbers[indexPath.row]
return cell
}
Firs of all please do not populate your tableview with multiple arrays. These arrays can easily go out of sync and can cause a crash. You should ideally create a struct class having name, age and photo as its elements. Then you should have an array of struct class to populate your table view.
Here as well in you name array you have 9 elements whereas your image array has 8 elements. This is causing your app to crash as cell for row at indexpath method is not able to find the 9th image.
cell.images.image = photo[indexPath.row]
So I took everyone's advice and when I run the code below, I get zero errors. But in the simulator, it shows an empty tableView and the image I placed above the tableView is another image from another View Controller. I don't know if it's the code or something else.
let nib = UINib(nibName: "CustomCell", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "Cell")
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = self.tableView.dequeueReusableCell(withIdentifier: "Cell") as? CustomCell else {return UITableViewCell()}
cell.images.image = photo[indexPath.row]
cell.name.text = names[indexPath.row]
cell.numbers.text = numbers[indexPath.row]
return cell
and my CustomCell
import UIKit
class CustomCell: UITableViewCell {
#IBOutlet weak var images: UIImageView!
#IBOutlet weak var name: UILabel!
#IBOutlet weak var numbers: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
I want to make simple UITabelView. I registered it's cell with my custom class which named as backgroundviewcell. I want to get Label of the selected cell. I tried many times but the output is coming nil value. I have also tried solution from stack overflow but it does not work for me. This is my cellForRowAt indexPath code :
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> backgroundViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "soundElementalcell") as! backgroundViewCell
let imageNames = sections[indexPath.section].images[indexPath.row]
cell.Labeltittle.text = sections[indexPath.section].items[indexPath.row]
cell.Labeltittle.textColor = UIColor(hex : 0x90BA27)
cell.LabelDetail.text = sections[indexPath.section].detail[indexPath.row]
//cell.detailTextLabel?.textColor = UIColor.red
//cell.isHighlighted = false
cell.backgroundColor = UIColor.clear
cell.iconview.image = UIImage(named: imageNames)
return cell
}
This is my didSelectRowAt indexPath code :
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let indexPath = tableView.indexPathForSelectedRow!
let currentCell = tableView.cellForRow(at: indexPath)!
celltext = currentCell.textLabel!.text
performSegue(withIdentifier: "showPlayer", sender: self)
}
and my Segue Method is :
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showPlayer" {
let playerVC = segue.destination as! PlayerViewController
playerVC.trackName = (celltext)! as String
}
}
This is working for me:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! YourCellType
let labelContent = cell.labelToAccess.text
}
First line creates an instance of your cell type (or standard cell, not my case).
The second saves the content of your label (labelToAccess in this case) in a constant.
Instead of accessing the text from the cell's label you need to access the array that you have used to fill the tableView's cell data.
So you need to use UITableViewDelegate method didSelectRowAtindexPath and access the array that you are using with your tableView methods.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(indexPath.row)
//Access the array that you have used to fill the tableViewCell
print(yourArray[indexPath.row])
}
Note: Once confirm that TableView delegate is properly connected with your ViewController so that it will call didSelectRowAt method when you select cell.
Edit: If you want to pass the data then try like this way.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showPlayer", sender: indexPath) //Pass indexPath as sender instead of self
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showPlayer" {
let playerVC = segue.destination as! PlayerViewController
let indexPath = sender as! IndexPath
playerVC.trackName = sections[indexPath.section].items[indexPath.row]
}
}
Try this 'Swift 4' -
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let currentCellTxt = yourTableView.cellForRow(at: indexPath)! as? YourCustomTableViewCell
print(currentCellTxt?.lblYourName?.text) // 'lblYourName' that you defined in your 'YourCustomTableViewCell'
}
You didn't set any text for textLabel. Hence it returns nil value.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> backgroundViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "soundElementalcell") as! backgroundViewCell
let imageNames = sections[indexPath.section].images[indexPath.row]
cell.Labeltittle.text = sections[indexPath.section].items[indexPath.row]
cell.Labeltittle.textColor = UIColor(hex : 0x90BA27)
cell.LabelDetail.text = sections[indexPath.section].detail[indexPath.row]
//cell.detailTextLabel?.textColor = UIColor.red
//cell.isHighlighted = false
cell.backgroundColor = UIColor.clear
cell.iconview.image = UIImage(named: imageNames)
return cell
}
In didSelectRow func try to get value from Labeltittle.text not from textLabel.text
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let indexPath = tableView.indexPathForSelectedRow!
let currentCell = tableView.cellForRow(at: indexPath)!
celltext = currentCell.Labeltittle.text
performSegue(withIdentifier: "showPlayer", sender: self)
}
I have static table and I set background color for tableview -> tableView.backgroundColor = UIColor.redColor() and when I have etc. 3 rows in static table then is tableview colored and 3 rows are white how can I fix background color for this cells? This code are not working for static
table ->
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel!.text = numbers[indexPath.row]
cell.backgroundColor = UIColor.greenColor()
return cell
}
In static Table View you don't have to implement cellForRowAtIndexPath. So I suggest you to implement the following code:
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
// Change the color of all cells
cell.backgroundColor = UIColor.greenColor()
}
Please don't use the cellForRowAtIndexPath method in this case because as you said you are using a static tableview.
Now coming to the solution. Today I just went through the same problem and the scenario was almost same as yours.
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
cell.backgroundColor = UIColor .grayColor()
}
One more thing I just wanna tell you that as per Apple's Document all the cell's default color is clear/white. So if you are trying to set the color through the Interface Builder or cellForRowAtIndexPath method it will return the white color by default if you are using iOS 7 / iOS 8 / iOS 9. So instead of declaring inside cellForRowAtIndexPath method use the above code. It will work fine.
Thanks
Hope this helped.
First of all make sure each cell has the background colour set to default in the UI mode. under the inspector attributes. Then in the code set
cell.backgroundcolor = UIColor.clearcolor()
Cheers
Sam
UITableViewCell.appearance().backgroundColor = UIColor.greenColor()
you can change the contentView background as it is a subview of cell:
cell.contentView.backgroundColor = UIColor.greenColor()
For swift 4:
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if _isAccountNotSet {
print("_isAccountNotSet\(_isAccountNotSet)")
cell.backgroundColor = .groupTableViewBackground
} else {
print("_isAccountNotSet\(_isAccountNotSet)")
cell.backgroundColor = .white
}
}
To change the background color of an intended row or rows use the following code:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
{
if indexPath.row == 2
{
cell.contentView.backgroundColor = UIColor.lightGray
}
}
This code changes the background color at IndexPath 2 (the third row.) You could change the 2 to which ever number you'd like or make it a list of numbers like so:
if indexPath.row == 2 || indexPath.row == 7
{
cell.contentView.backgroundColor = UIColor.lightGray
}
you could also sub in a variable instead of the 2 to make it more dynamic.
Good Luck!