get label text from cell at row - swift

is there another way i can get the string from the refinementslabel.text when I call did select row , because i think/apparently in the new XCode calling
let serviceTypeCell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! ServiceCell
crashes my app
so i am looking for code like
let text = refinementsLabel.text at indexpath.row
but I'm not sure exactly what to type?
let sections = ["All Users & Services","Automotive", "Building & Construction", "Cleaning", "Landscaping & Gardening"]
let services = [["All Users & Services"],["Automotive"],["Air Conditioning & Heating","Bricklaying", "Carpentry","Carpet Layer","Concreting & Paving","Electrical","Fencing and Gates","Flooring","Handyman","Other","Painting & Decorating","Pet Control","Plastering","Plumbing","Roofing","Rubbish Removal","Scaffolding","Tiling"], ["Cleaning"],["Landscaping & Gardening"]]
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let serviceTypeCell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! ServiceCell
var service = serviceTypeCell.refinementsLabel.text
service = services[indexPath.section][indexPath.row]
defaults.set(service, forKey: "Service being searched")
guard let serviceBeingSearched = self.defaults.string(forKey: "Service being searched") else { return }
navigationItem.title = serviceBeingSearched
tableView.reloadData()
}

Below method is using when create new cell that method is use in cellforRow if you are using that method than app crash
let serviceTypeCell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! ServiceCell
If you get cell in didselect method you can use below code
let cell = tableView.cellForRow(at: indexPath) as? ServiceCell
if you get string from you can select cell than use below line
let service = services[indexPath.section][indexPath.row]

Related

Getting a indexPath.row with a matching value

So, I have two Json requests from the same API with the difference, that one is from today and the other one from yesterday. I have them displayed in "MyCell" in my TableView and the result is this.
This is the code :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! CustomTableViewCell
let today = today[indexPath.row]
let yesterday = yesterday[indexPath.row]
let nameOfThe place = today.local
let salesToday = today.sales
let nameOfThePlaceYesterday = yesterday.local
let salesYesterday = yesterday.sales
}
So far, so good. Thats whats I wanted. The problem start when some places havent open yesterday( for example A and B). I get this:
Whats happening is, since there isnt the same "numberOfRowsInSection" for both days, it just populates cell in order but mismatching places. Question:
How do I get "indexPath.row" with a matching value of the other indexPath.row. In this case it would be a name of the place.
Thank you
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! CustomTableViewCell
let today = today[indexPath.row]
let nameOfThe place = today.local
let salesToday = today.sales
if let yesterday = yesterday[safe: indexPath.row] {
let nameOfThePlaceYesterday = yesterday.local
let salesYesterday = yesterday.sales
}
}

Fill UITableView Cell Labels manually

I'm trying to fill up a UITableView's cell's labels.
My problem is that it's just filling up the first cell.
This is what I got so far (three Cells should be filled, but only the first is)
import UIKit
class StatsViewController: UITableViewController {
var vc = ViewController()
override func viewDidLoad() {
super.viewDidLoad()
// tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
// tableView.reloadData()
//tableView.delegate = self
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) //ACHTUNG: "ListItem" ist der Name meiner Zelle
let cell2 = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath)
let cell3 = tableView.dequeueReusableCell(withIdentifier: "cell3", for: indexPath)
let cell4 = tableView.dequeueReusableCell(withIdentifier: "cell4", for: indexPath)
let cell5 = tableView.dequeueReusableCell(withIdentifier: "cell5", for: indexPath)
if let label = cell.viewWithTag(1000) as? UILabel {
if indexPath.row == 0{
label.text = "*** Quittung ***"
//label.font = UIFont(name: label.font.fontName, size: 20)
}
}
if let label2 = cell2.viewWithTag(1001) as? UILabel {
if indexPath.row == 1{
label2.text = "------------------"
}
}
if let label3 = cell3.viewWithTag(1002) as? UILabel {
if indexPath.row == 2{
label3.text = "*SAEULENNR. 2 " + String( vc.preisProLiter) + "EUR/Liter*"
}
}
return cell
}
}
As you can see: I want to fill 5 Cells manually.
Whereas the first cell has idenifier "cell" and the first cell's label has Tag = 1000.
The second cell has idenifier "cell2" and the second cell's label has Tag = 1001.
And so on..
This is a screenshot of how it looks right now:
Screenshot
Thanks for any help!
If you assign the same indexPath to a bunch of cells, iOS will override all cells and bind the given identifier to the cell, then populates it.
Do like so
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
//.
//.
//.
return cell
} else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath)
//.
//.
//.
return cell
} else if others
//.
//.
//.
//.
} else {
return UItableViewCell()
}
Plus, you can optimize it a little by casting the cells to its type
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TheTypeOfTheCell
cell.yourLabel.text = "*** Quittung ***"
//.
//.
//.
return cell

Loading Multiple Xib View in one cell

My tableview has 3layer
first: Header
second: section
third: xibviews
My tableviewCell load Xibs view depend on indexPath.row
For example indexPath.row is at 2 , i want to load CDFlightXibView
But it makes it too slow when scrolling
What should i do ?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.section {
case 0:
print("contract detail")
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let vieww = Bundle.main.loadNibNamed("CDContractXibView", owner: self, options: nil)?.first as? CDContractXibFile
vieww?.fillData()
cell.contentView.addSubview(vieww!)
vieww?.frame = cell.contentView.frame
vieww?.center = cell.contentView.center
return cell
case 1:
print("passenger")
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let vieww = Bundle.main.loadNibNamed("CDPassengerInFlightXibView", owner: self, options: nil)?.first as? CDPassengerInFlightXibFile
vieww?.fillData()
cell.contentView.addSubview(vieww!)
vieww?.frame = cell.contentView.frame
vieww?.center = cell.contentView.center
return cell
case 2:
print("flight")
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let vieww = Bundle.main.loadNibNamed("CDFlightXibView", owner: self, options: nil)?.first as? CDFlightXibFile
vieww?.fillData()
vieww?.detailBtn.addTarget(self, action: #selector(showPassenger(_:)), for: .touchUpInside)
vieww?.detailBtn.tag = indexPath.row
cell.contentView.addSubview(vieww!)
vieww?.frame = cell.contentView.frame
vieww?.center = cell.contentView.center
return cell
default:
print("nothing")
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
return cell
}
You are loading multiple xib files every time you scroll and all this actions need computations that cause laggy scroll.
Try design specific UITableViewCell for each state and dequeue them by indexPath.section cases.

Image are not showing in table View

i am trying to get a list of items from mysql and display them in the app.
names appear but the image and price dose not.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// let cell = tableView.dequeueReusableCell(withIdentifier: "BasicCell", for: indexPath)
var cell:UITableViewCell? =
tableView.dequeueReusableCell(withIdentifier: "BasicCell", for: indexPath)
if (cell == nil)
{
cell = UITableViewCell(style: UITableViewCellStyle.subtitle,
reuseIdentifier: "BasicCell")
}
// Get the location to be shown
let item: Location = locations[indexPath.row]
// let price=locations[indexPath.row].price
let price=(item.price as NSString).floatValue
let cellPrice = String(format: "%.2f",price)
let serverurl=NSURL(string: "https://myoscapp.com/boot/images/")
let imageaddress = locations[indexPath.row].image
let imageURL = NSURL.init(string: imageaddress, relativeTo: serverurl! as URL)
cell?.textLabel?.text=locations[indexPath.row].name
cell?.detailTextLabel?.text = cellPrice
cell?.imageView?.sd_setImage(with: imageURL! as URL )
cell?.setNeedsLayout() //invalidate current layout
cell?.layoutIfNeeded() //update immediately
return cell!
}
i got everything to work like this. i don't know if for:indexPath is going to have an effect but i don't see anything
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// let cell = tableView.dequeueReusableCell(withIdentifier: "BasicCell", for: indexPath)
let cell = UITableViewCell(style: UITableViewCellStyle.subtitle,
reuseIdentifier: "BasicCell")
// Get the location to be shown
let item: Location = locations[indexPath.row]
// let price=locations[indexPath.row].price
let price=(item.price as NSString).floatValue
let cellPrice = String(format: "%.2f",price)
let serverurl=NSURL(string: "https://myoscapp.com/boot/images/")
let imageaddress = locations[indexPath.row].image
let imageURL = NSURL.init(string: imageaddress, relativeTo: serverurl! as URL)
cell.textLabel?.text=locations[indexPath.row].name
cell.detailTextLabel?.text = cellPrice
cell.imageView?.sd_setImage(with: imageURL! as URL )
cell.setNeedsLayout() //invalidate current layout
cell.layoutIfNeeded() //update immediately
return cell
}

Swift 3 Breaks Cell For Row At Index Path

This code was from a now inactive tutorial that helped me load in data to a table view. Since the tutorial was written in Swift 2.0, I believe that this was changed in Swift 3. I know that the override function itself was changed, which I handled. But now, it brings me a Thread 1: EXC_BAD_INSTRUCTION(code=EXC_1386_INVOP, subcode=0x0) error.
Update: I have tried multiple things including creating a custom class for the cell. I still either get the same error I listed above, or a Thread 1: Signal SIGABRT error on the first line of my App Delegate file. Creating a breakpoint hasn't helped me because I know where the error is coming from.
import UIKit
import Firebase
import FirebaseDatabase
struct postStruct {
let title : String!
let message : String!
}
class LoggedInController: UITableViewController {
var posts = [postStruct]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("Posts").queryOrderedByKey().observe(.childAdded, with: {
snapshot in
let snapshotValue = snapshot.value as? NSDictionary
let title = snapshotValue!["title"] as? String
let message = snapshotValue!["message"] as? String
self.posts.insert(postStruct(title: title, message: message), at: 0)
self.tableView.reloadData()
})
post()
}
func post(){
let title = "Title"
let message = "Message"
let post : [String : AnyObject] = ["title" : title as AnyObject,
"message": message as AnyObject]
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("Posts").childByAutoId().setValue(post)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell")
let label1 = cell?.viewWithTag(1) as! UILabel
label1.text = posts[indexPath.row].message
let label2 = cell?.viewWithTag(2) as! UILabel
label2.text = posts[indexPath.row].message
return cell!
}
}
Update 2: Here is the new code I used. It's not pretty and only gets the title.
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
cell?.textLabel?.text = posts[indexPath.row].title
cell?.detailTextLabel?.text = posts[indexPath.row].message
return cell!
} else {
let label1 = cell?.viewWithTag(1) as? UILabel
label1?.text = posts[indexPath.row].title
let label2 = cell?.viewWithTag(2) as? UILabel
label2?.text = posts[indexPath.row].message
return cell!
}
}
Using dequeueReusableCell, you are accessing cell which doesn't exists. To make your code work change the below line:
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
To
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
Ok this code let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") produces an optional called cell that may or may not contain a a valid instance of UITableViewCell. Optionals in Swift are a way to safeguard against nil values, you can read more about optionals here: Optionals
On the first run when your table view wants to load its data it calls all the required methods of your UITableViewDataSource. The first run is a critical one because there aren't any instances of the UITableViewCell the table view can dequeue yet. To solve your problem you have to do something similar to the code below:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell?.textLabel?.text = "New value"
cell?.detailTextLabel?.text = "New value"
return cell!
} else {
cell?.textLabel?.text = "" //reset value
cell?.detailTextLabel?.text = "" // resetValue
cell?.textLabel?.text = "New value"
cell?.detailTextLabel?.text = "New value"
return cell!
}
}
Code similar to the one above are usually used to programmatically add an instance of UITableViewCell. However, if you used interface builder to add a prototype cell use the let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) method to dequeue your cells in which case it does not return an optional and you do not need to do all the if / else blocks.
Something else I wanted to mention about your code is finding sub views buy their ID will not produce a very object oriented code and that maybe the source of your errors where the compiler can not find the sub views. The better way would be to use one of the built in instances of UITableViewCell such as .default or alliteratively you could subclass the said class and make your very own custom cells.
Hope this helped!
Try this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell:UITableViewCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as UITableViewCell!
let label1 = cell.viewWithTag(1) as! UILabel
label1.text = posts[indexPath.row].message
let label2 = cell.viewWithTag(2) as! UILabel
label2.text = posts[indexPath.row].message
return cell
}
Edited
Make Sure you did these things
UITableViewController
In viewDidLoad()
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier:"catCell" )
let catNib : UINib = UINib.init(nibName: "TableViewCategoryCell", bundle: nil)
self.tableView.register(catNib, forCellReuseIdentifier: "TableViewCategoryCell")
In cellForRowAt indexPath
let cell : OPM_AlarmTableViewCategoryCell = tableView.dequeueReusableCell(withIdentifier:"OPM_AlarmTableViewCategoryCell" ) as! OPM_AlarmTableViewCategoryCell!
cell.categoryLabel?.text = "Some Text"
return cell
UITableviewCell.XIB
Hope u did these things
UITableviewCell
Make sure the dot appears so that the #IBOutlet is connected with the
xib label