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.
Related
I have 3 UITableViewCell with XIB files but on my tableview I can't display my three UITableViewCell, only can load the first two
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (indexPath.item % 2 == 0) {
let cell = tableView.dequeueReusableCell(withIdentifier: "CaptureNameTableViewCell", for: indexPath) as! CaptureNameTableViewCell
cell.nameTextField.text = ""
cell.nameTextField.tag = indexPath.row
cell.nameTextField.delegate = self
return cell
} else if indexPath.section == 2 {
let cell = tableView.dequeueReusableCell(withIdentifier: "CapturePhotoTableViewCell", for: indexPath) as! CapturePhotoTableViewCell
cell.displayImage = imageView
cell.cellDelegate = self
cell.selectImage.tag = indexPath.row
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "PieChartTableViewCell", for: indexPath) as! PieChartTableViewCell
return cell
}
}
You need to register the xib tableViewCells inside of the tableViewController:
First create an id property inside of the cells xib class, to use as the cell’s reuse identifier (make the name of this the same as your reuse identifier for the cell which you set in the xib file):
let id = "cellIdentifier" // Name this appropriately
Then create a nib method inside of the cell's xib class:
func nib() -> UINib {
return UINib(named: "cellIdentifier", bundle: nil)
}
Then inside of a lifecycle method such as viewDidLoad():
tableView.register(nib: cell.nib, forCellReuseIdentifier: cell.id)
Finally, specify which cells you want to be where in the table view at which indexPath.row. (Which row in the table view):
switch indexPath.row {
case 0: // First cell
let cell = tableView.dequeueReusableCell(withIdentifier: "CaptureNameTableViewCell", for: indexPath) as! CaptureNameTableViewCell
// Configure cell as before
return cell
case 1: // Second cell
let cell = tableView.dequeueReusableCell(withIdentifier: "CapturePhotoTableViewCell", for: indexPath) as! CapturePhotoTableViewCell
// Configure cell as before
return cell
case 2: // Third cell
let cell = tableView.dequeueReusableCell(withIdentifier: "PieChartTableViewCell", for: indexPath) as! PieChartTableViewCell
// Configure cell as before
return cell
default:
return UITableViewCell() // This should not be reached but a switch statement must cover all possibilities.
}
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
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]
I created a collection view in table view cell and added a segment control on the navigation bar of the table view. How can I change the collection cell item when the segment outlet and action is on table view controller?
I tried this on table view controller but get this error:
request for number of items before section 2147483647 when there are only 1 sections in the collection view
#IBAction func mySegAction(_ sender: UISegmentedControl) {
switch mySeg.selectedSegmentIndex
{
case 0:
print("0")
case 1:
print("1")
let indexPath = IndexPath()
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CategoryCollectionViewCell
cell.cateLabel.text! = nameArray2[indexPath.row]
default:
break;
}
}
Table view cell controller:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CategoryCollectionViewCell
cell.cateLabel.text! = nameArray[indexPath.row]
// I tried this code but fail
if AddViewController().mySeg?.selectedSegmentIndex == 1 {
cell.cateLabel.text! = nameArray2[indexPath.row]
}
return cell
}
I want to change cateLabel.text! = nameArray[indexPath.row] to nameArray2[indexPath.row] when the Segment is changed, How to do that?
Calling tableView.reloadData() on Action and collectionView.reloadData() on cellForRowAt
#IBAction func mySegAction(_ sender: UISegmentedControl) {
switch mySeg.selectedSegmentIndex{
case 0:
segment = 0
UserDefaults.standard.setValue(segment, forKey:"segment")
UserDefaults.standard.synchronize()
case 1:
segment = 1
UserDefaults.standard.setValue(segment, forKey:"segment")
UserDefaults.standard.synchronize()
default:
break;
}
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 1{
let cell1 = tableView.dequeueReusableCell(withIdentifier: "AddViewCell2", for: indexPath)
return cell1
}else if indexPath.row == 2{
let cell2 = tableView.dequeueReusableCell(withIdentifier: "AddViewCell3", for: indexPath)
return cell2
}else if indexPath.row == 3{
let cell3 = tableView.dequeueReusableCell(withIdentifier: "AddViewCell4", for: indexPath)
return cell3
}else if indexPath.row == 4{
switch segment {
case 0:
let cell4 = tableView.dequeueReusableCell(withIdentifier: "AddViewCell5", for: indexPath) as! AddViewCell
cell4.collectionView.reloadData()
return cell4
case 1:
let cell4 = tableView.dequeueReusableCell(withIdentifier: "AddViewCell5", for: indexPath) as! AddViewCell
cell4.collectionView.reloadData()
return cell4
default:
break
}
}
let cell = tableView.dequeueReusableCell(withIdentifier: "AddViewCell1", for: indexPath)
return cell
}
On the table view cell class:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CategoryCollectionViewCell
let segment = UserDefaults().value(forKey: "segment") as! Int
//print("segment here")
//print(segment)
switch segment {
case 0:
cell.cateLabel.text! = nameArray[indexPath.row]
cell.cateImg.image = imageName[indexPath.row]
case 1:
cell.cateLabel.text! = nameArray2[indexPath.row]
cell.cateImg.image = imageName[indexPath.row]
default:
break;
}
return cell
}
I have this code:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: IndexPath) as? Cell
But IndexPath is showing an error:
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: IndexPath) as? Cell
In this line you're passing IndexPath Class instead of the indexPath parameter from the function. replace it with:
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? Cell