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
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 setting up survey screen consists of table view so that each cell has table view of checkboxes the problem is that when I check box and scroll down I find that another cell dequeued with checkbox selected.
I have tried to change selection state in prepare for reuse but didn't work
this code for checkbox table view
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = taskActionOptionTableView.dequeueReusableCell(withIdentifier: Constants.TASK_CHOOSE_OPTIONCELL_ID, for: indexPath) as? TaskChooseOptionCell
if taskResponseActionId == nil {
taskResponseAction = TaskResponseAction()
}
cell?.taskCheckBox.boxType = .circle
cell?.taskCheckBox.markType = .radio
cell?.taskCheckBox.boxLineWidth = 2
cell?.delegate = self
if cell?.taskCheckBox.checkState == .checked {
print("checked")
}
if taskAction?.taskDependentActions.count != 0 {
cell?.scoreOperator = taskAction?.taskDependentActions[indexPath.section].scoreOperator
cell?.scoreNumberValue = taskAction?.taskDependentActions[indexPath.section].scoreNumberValue
}
cell?.taskActionOptionScoreValue = taskAction?.taskActionOptions[indexPath.row].taskActionOptionScoreValue
if cell == nil {
cell = TaskChooseOptionCell.customCell
}
if isDependent {
cell?.taskDepActionOption = taskDependentActionOptions?[indexPath.row]
return cell!
} else {
cell?.taskActionOption = taskActionOptions?[indexPath.row]
return cell!
}
}
And this for the main table view cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let id = task?.taskActions[indexPath.section].actionTypeId
let cellType = TaskActionType.allCases.filter {
return $0.id == id
}.first
guard let cellDescType = cellType else { return UITableViewCell() }
switch cellDescType {
case .date:
let dateCell = tableView.dequeueReusableCell(withIdentifier: Constants.DATE_CELL_ID, for: indexPath) as! DateCell
dateCell.taskMaterial = taskActionsOnMaterialArray[indexPath.row].material
return dateCell
case .multiChoice:
let multiChoiceCell = tableView.dequeueReusableCell(withIdentifier: Constants.MULTI_CHOOSE_CELL_ID, for: indexPath) as! MultiChooseCell
multiChoiceCell.delegate = self
multiChoiceCell.taskMaterial = task?.taskRestrictedMaterials[indexPath.row]
multiChoiceCell.taskAction = task?.taskActions[indexPath.section]
multiChoiceCell.taskActionOptions = Array((task?.taskActions[indexPath.section].taskActionOptions)!)
return multiChoiceCell
case .text:
let textCell = tableView.dequeueReusableCell(withIdentifier: Constants.TEXT_CELL_ID, for: indexPath) as! TextViewCell
return textCell
case .singleChoice:
let singleChoiceCell = tableView.dequeueReusableCell(withIdentifier: Constants.SINGLE_CHOICE_CELL_ID, for: indexPath) as! SingleChoiceCell
singleChoiceCell.delegate = self
singleChoiceCell.taskMaterial = task?.taskRestrictedMaterials[indexPath.row]
singleChoiceCell.taskAction = task?.taskActions[indexPath.section]
singleChoiceCell.taskActionOptions = Array((task?.taskActions[indexPath.section].taskActionOptions)!)
return singleChoiceCell
case .number:
let numberCell = tableView.dequeueReusableCell(withIdentifier: Constants.NUMBER_CELL_ID, for: indexPath) as! NumberCell
return numberCell
}
}
In your data model you can add a variable like var done : Bool = " " and set it to false initially and toggle it on didSelectRow to true or false accordingly and check this variable on the time of setting accessoryType. If its true then set it to .checked else set it to .none.
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 am new to swift and trying to implement collectionView function in a ViewController.Now I have three types of UICollectionViewCell,here is my code:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == self.collectionViewCategory {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: categoryIdentifier, for: indexPath as IndexPath) as! CategoryCell
cell.CategoryIcon.image = self.categoryItems[indexPath.item]
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.layer.borderWidth = 1
cell.layer.cornerRadius = 5
return cell
}
else if collectionView == self.collectionViewHour {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: hourIdentifier, for: indexPath as IndexPath) as! HourCell
cell.hourItem.text = self.hourItems[indexPath.item]
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.layer.borderWidth = 1
cell.layer.cornerRadius = 5
return cell
}
else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: minuteIdentifier, for: indexPath as IndexPath) as! MinuteCell
cell.minuteItem.text = self.minuteItems[indexPath.item]
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.layer.borderWidth = 1
cell.layer.cornerRadius = 5
return cell
}
}
Can I use switch statement to achieve the same effect?Make the code look a little more elegant?
I hope my code looks like this:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:UICollectionViewCell
switch collectionView {
case self.collectionViewCategory:
cell = collectionView.dequeueReusableCell(withReuseIdentifier: categoryIdentifier, for: indexPath as IndexPath) as! CategoryCell
cell.CategoryIcon.image = self.categoryItems[indexPath.item]
case self.collectionViewHour:
cell = collectionView.dequeueReusableCell(withReuseIdentifier: hourIdentifier, for: indexPath as IndexPath) as! HourCell
cell.hourItem.text = self.hourItems[indexPath.item]
default:
//do nothing.
}
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.layer.borderWidth = 1
cell.layer.cornerRadius = 5
return cell
}
But I got a lot of mistakes, and I do not know how to fix them.
You can try to assign each collectionView a unique tag like so
collectionView.tag = 1
and then use the tag as the identifier:
switch collectionView.tag {
case 0:
// some code
case 1:
// some code
default:
// some code
}
If you're using your collectionViews inside UITableViewCells you can set each collectionView.tag to be indexPath.section or indexPath.row within tableView(_ tableView: willDisplay cell: forRowAt indexPath:).
Here's a nice subclass you could use:
class CollectionViewTableViewCell: UITableViewCell {
#IBOutlet weak var collectionView: UICollectionView!
func setCollectionViewDataSourceDelegate(dataSource: UICollectionViewDataSource?, dataDelegate: UICollectionViewDelegate?, forSection section: Int) {
collectionView.delegate = dataSource as! UICollectionViewDelegate?
collectionView.dataSource = dataDelegate as! UICollectionViewDataSource?
collectionView.tag = section
collectionView.reloadData()
}
}
and then in your view controller implement
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let tableViewCell = cell as? CollectionViewTableViewCell else { return }
tableViewCell.setCollectionViewDataSourceDelegate(dataSource: self, dataDelegate: self, forSection: indexPath.section)
}
Hope this help. Not testing at all. If any issues, can you take a snip ?
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:UICollectionViewCell
switch collectionView {
case self.collectionViewCategory:
let categoryCell = collectionView.dequeueReusableCell(withReuseIdentifier: categoryIdentifier, for: indexPath as IndexPath) as! CategoryCell
categoryCell.CategoryIcon.image = self.categoryItems[indexPath.item]
cell = categoryCell
case self.collectionViewHour:
let hourCell = collectionView.dequeueReusableCell(withReuseIdentifier: hourIdentifier, for: indexPath as IndexPath) as! HourCell
hourCell.hourItem.text = self.hourItems[indexPath.item]
cell = hourCell
default:
//do nothing.
}
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.layer.borderWidth = 1
cell.layer.cornerRadius = 5
return cell
}
I have a tableView with two different custom cell. One cell have a switch and other a image, I have Two separated custom class for the cells, identifiers.. but I can't see this. i don't know if I need change the configuration in story board to dynamic or other thing.. Can I show two different custom cells
Thanks!
Check the criteria for showing each specific custom cell, then cast to that cell as needed:
override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
if (criteria for cell 1) {
let cell = tableView!.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as? Cell1
return (cell)
}
else {
let cell = tableView!.dequeueReusableCellWithIdentifier("cell2", forIndexPath: indexPath) as? Cell2
return (cell)
}
}
Swift 3
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath -> UITableViewCell {
if (criteria for cell 1) {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! Cell1
return cell
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as! Cell2
return cell
}
}
override func tableView(tableView: UITableView?,cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
if (...) {
let cell : Mycell1 = tableView!.dequeueReusableCellWithIdentifier("Mycell1", forIndexPath: indexPath) as? Mycell1
return cell
}
else {
let cell : Mycell2 = tableView!.dequeueReusableCellWithIdentifier("Mycell2", forIndexPath: indexPath) as? Mycell2
return cell
}
}