I have two sections in a table view that contains data. When clicking on section 2's delete button it removes all content from the table view. I'm using the table view header for section separation.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if section == 0 {
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: DiagnosisTVHeaderCell.self)) as? DiagnosisTVHeaderCell else {return UITableViewCell()}
cell.delegate = self
cell.selectionStyle = .none
return cell
} else if section == 1 {
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: EMRAttachmentsCell.self)) as? EMRAttachmentsCell else {return UITableViewCell()}
cell.selectionStyle = .none
cell.delegate = self
return cell
}
return UIView()
}
func deleteTableCell(index: Int) {
if attachmentTypeDiagnosis.isEmpty == false {
attachmentTypeDiagnosis.remove(at: index)
attachmattachmentInfoDiagnosis.remove(at: index)
tableviewDiagnosis.deleteRows(at: [IndexPath(row: index, section: 1)], with: .left)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: DiagnosisListingTVCell.self)) as? DiagnosisListingTVCell else {return UITableViewCell()}
cell.selectionStyle = .none
cell.lblTitle.attributedText = "\(self.presenter?.emrRecord?.emrDetails?.emrDiagnosis?[indexPath.row].name ?? "")".style(using: .syne_regular_18_black)
cell.lblDes.attributedText = "\(self.presenter?.emrRecord?.emrDetails?.emrDiagnosis?[indexPath.row].description ?? "")".style(using: .syne_regular_14_grey)
return cell
}
Related
I tried to manage from custom segment control cell into ViewController's tableview cell.
This is My custom segment control class:
protocol SegmentControllerCellDelegate: AnyObject {
func manageSegmentControl(cell: SegmentControllerCell)}
class SegmentControllerCell: UITableViewCell, ReusableView, NibLoadableView {
#IBOutlet weak var segmentController: UISegmentedControl!
weak var delegate: SegmentControllerCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
setupUI()
}
#IBAction func tappedSegmentControll(_ sender: UISegmentedControl) {
self.delegate?.manageSegmentControl(cell: self )
}}
And this is my view controller:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch BrandSection(rawValue: indexPath.section)! {
case .profile:
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: BrandTableViewCell.self), for: indexPath) as? BrandTableViewCell else { return UITableViewCell() }
cell.cellType = .brandPage
return cell
case .segment:
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SegmentControllerCell.self), for: indexPath) as? SegmentControllerCell else { return UITableViewCell() }
cell.delegate = self
return cell
case .products:
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: BrandProductionsCell.self), for: indexPath) as? BrandProductionsCell else { return UITableViewCell() }
return cell
}
}
extension BrandProfileVC: SegmentControllerCellDelegate {
func manageSegmentControl(cell: SegmentControllerCell) {
if cell.segmentController.selectedSegmentIndex == 0 {
self.brandTableView.reloadData()
print("index 0")
} else if cell.segmentController.selectedSegmentIndex == 1 {
self.brandTableView.reloadData()
print("index 1")
}
}}
I just want to show when I clicked segment control tab, different cell under the segment control.
Please try to set the cell.tag as indexPath.row from cellForRow and then try to print the cell.tag inside the manageSegmentControl in your ViewController
This is the Code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch BrandSection(rawValue: indexPath.section)! {
case .profile:
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: BrandTableViewCell.self), for: indexPath) as? BrandTableViewCell else { return UITableViewCell() }
cell.cellType = .brandPage
cell.tag = indexPath.row
return cell
case .segment:
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SegmentControllerCell.self), for: indexPath) as? SegmentControllerCell else { return UITableViewCell() }
cell.delegate = self
cell.tag = indexPath.row
return cell
case .products:
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: BrandProductionsCell.self), for: indexPath) as? BrandProductionsCell else { return UITableViewCell() }
cell.tag = indexPath.row
return cell
}
}
extension BrandProfileVC: SegmentControllerCellDelegate {
func manageSegmentControl(cell: SegmentControllerCell) {
if cell.segmentController.selectedSegmentIndex == 0 {
self.brandTableView.reloadData()
print(cell.tag)
} else if cell.segmentController.selectedSegmentIndex == 1 {
self.brandTableView.reloadData()
print(cell.tag)
}
}
}
I have three sections, the first one stores the user's information , the second one contains the field for adding posts, and the third one is posts.
And when scrolling, I start to load the section with the addition of posts and the user information section in the posts section
This is my code
UIViewController extension UITableViewDataSource :
func numberOfSections(in tableView: UITableView) -> Int {
presenter?.numberOfSections() ?? 0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let section = UserPageTypeSection(rawValue: section) else { return 0 }
return presenter?.numberOfRowsInSection(section: section) ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let section = UserPageTypeSection(rawValue: indexPath.section),
let userInfo = presenter?.cellForRowAt(section: section, indexRow: indexPath.row)
else { return UITableViewCell() }
switch userInfo.type {
case .userInfo:
guard let cell = tableView.dequeueReusableCell(withIdentifier: ProfileInfoTableViewCell.reuseIdentifier, for: indexPath) as? ProfileInfoTableViewCell else { return UITableViewCell() }
cell.userInformation(userData: userInfo.data?[indexPath.row] as? UserProfile)
return cell
case .userAddPost:
guard let cell = tableView.dequeueReusableCell(withIdentifier: ProfileInfoTableViewCell.reuseIdentifier, for: indexPath) as? ProfileInfoTableViewCell else { return UITableViewCell() }
cell.addPostUser()
return cell
case .userPost:
guard let cell = tableView.dequeueReusableCell(withIdentifier: ProfileInfoTableViewCell.reuseIdentifier, for: indexPath) as? ProfileInfoTableViewCell else { return UITableViewCell() }
cell.post(text: "POST")
return cell
default:
return UITableViewCell()
}
I have a UICollectionView with 4 UICollectionViewCells. Each cell contains a UITableView with a varying number of cells.
I have an array from which I need to pass a value (depending on the indexPath) into the cell. My problem is that it always gives me nil when I try to do this.
So for example I have this array:
let arrayOfStrings = ["test1", "test2", "test3", "test4"]
I have this code in my collection view's cellForItemAt method:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "testCollectionViewCell", for: indexPath) as! TestCollectionViewCell
cell.myString = arrayOfStrings[indexPath.row]
cell.label.text = "This text is set."
return cell
}
The cell's label is set properly, but when I try to print myString in the cell's table view's cellForRowAt method it always returns nil.
I need the string because I plan to manipulate the table views depending on the string passed in.
So why is this happening and what can be done?
You can try like this
extension HomeViewController : UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "DealTableViewCell", for: indexPath) as! DealTableViewCell
cell.DealCollectionView.dataSource = self
cell.DealCollectionView.delegate = self
cell.DealCollectionView.tag = 10101
return cell
} else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "BusinessTableViewCell", for: indexPath) as! BusinessTableViewCell
cell.BusinessCollectionView.dataSource = self
cell.BusinessCollectionView.delegate = self
cell.BusinessCollectionView.tag = 10102
return cell
} else if indexPath.row == 2 {
let cell = tableView.dequeueReusableCell(withIdentifier: "FilterTableViewCell", for: indexPath) as! FilterTableViewCell
cell.FilterCollectionView.dataSource = self
cell.FilterCollectionView.delegate = self
cell.FilterCollectionView.tag = 10103
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "ComboTableViewCell", for: indexPath) as! ComboTableViewCell
cell.ComboCollectionView.dataSource = self
cell.ComboCollectionView.delegate = self
cell.ComboCollectionView.tag = 10104
return cell
}
}
}
Add the collection view to each tableview cell and set delegate in tableview cell
extension HomeViewController : UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView.tag == 10101 {
return 3
} else if collectionView.tag == 10102 {
return 3
} else if collectionView.tag == 10103 {
return 3
} else if collectionView.tag == 10104 {
return 3
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView.tag == 10101 {
let cell = collectionView.dequeueReusableCell(withIdentifier: "DealCollectionViewCell", for: indexPath) as! DealCollectionViewCell
return cell
} else if collectionView.tag == 10102 {
let cell = collectionView.dequeueReusableCell(withIdentifier: "BusinessCollectionViewCell", for: indexPath) as! BusinessCollectionViewCell
return cell
} else if collectionView.tag == 10103 {
let cell = collectionView.dequeueReusableCell(withIdentifier: "FilterCollectionViewCell", for: indexPath) as! FilterCollectionViewCell
return cell
} else if collectionView.tag == 10104 {
let cell = collectionView.dequeueReusableCell(withIdentifier: "ComboCollectionViewCell", for: indexPath) as! ComboCollectionViewCell
return cell
}
return UICollectionViewCell()
}
}
For reload the collectionView in use
if let cell = self.tableView.cellForRow(at: IndexPath(row: i, section: 0)) as?
tableViewCell {
cell.collectionView.reloadData()
}
I am creating a TableView that starts with an image at the top, approximately 5 cells of parsed json, another image, approximately 3 more cells of parsed json, and another image.
I have 3 custom nibs that I am using. Each one is unique.
I get an "Index out of range" error on the line "let item = page?.collapsibles[indexForSecondSetTableViewCells]"
Here is my code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let currentIndex = indexPath.row - 1
let numberofCarousels = self.page?.carousels.count
let indexAfterCarousels = numberofCarousels ?? 00 + 1
let indexForSecondSetTableViewCells = indexAfterCarousels + 1
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "pipesOne", for: indexPath) as! Pipes1TableViewCell
cell.pipesOne.image = UIImage(named: "WhatsNew1")
return cell
}
if indexPath.row == indexAfterCarousels {
let cell = tableView.dequeueReusableCell(withIdentifier: "pipesOne", for: indexPath) as! Pipes1TableViewCell
cell.pipesOne.image = UIImage(named: "WhatsNew2")
return cell
}
if indexPath.row == indexForSecondSetTableViewCells {
let cell = tableView.dequeueReusableCell(withIdentifier: "collapsibleCell", for: indexPath) as! CollapsiblesTableViewCell
let item = page?.collabsible[indexForSecondSetTableViewCells]
cell.collabsibleTitle.text = item?.title
cell.collabsibleDescription.text = item?.content
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "newsTableViewCell", for: indexPath) as! NewsTableViewCell
let item = page?.carousels[currentIndex]
cell.newsTitle.text = item?.title
cell.newsText.text = item?.caption
cell.newsImage.kf.setImage(with: page?.carousels[currentIndex].imageURL)
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (page?.carousels.count ?? 0) + 1 + (page?.collapsibles.count ?? 0)
}
Update: I simplified the code to use the same json object twice and so that each item maps to exactly the cell that it should go to and I still get the "Fatal error: Index out of range" error at row 7 with let item = page?.collapsible[indexPath.row]
New code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "pipesOne", for: indexPath) as! Pipes1TableViewCell
cell.pipesOne.image = UIImage(named: "WhatsNew1")
return cell
}
if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "newsTableViewCell", for: indexPath) as! NewsTableViewCell
let item = page?.carousels[indexPath.row]
cell.newsTitle.text = item?.title
cell.newsText.text = item?.caption
cell.newsImage.kf.setImage(with: page?.carousels[indexPath.row].imageURL)
return cell
}
if indexPath.row == 6 {
let cell = tableView.dequeueReusableCell(withIdentifier: "pipesOne", for: indexPath) as! Pipes1TableViewCell
cell.pipesOne.image = UIImage(named: "WhatsNew2")
return cell
}
if indexPath.row == 7 {
let cell = tableView.dequeueReusableCell(withIdentifier: "collapsibleCell", for: indexPath) as! CollapsiblesTableViewCell
let item = page?.collapsibles[indexPath.row]
cell.collabsibleTitle.text = item?.title
cell.collabsibleDescription.text = item?.content
return cell
}
return UITableViewCell()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 11
}
Try to print("\(indexPath)") in
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("\(indexPath)")
}
Then you will know how many rows it successfully shows before crash.
Then in cellForRowAt put conditional break point such it stops when indexPath is the one it crashed.
Now do po (page?.carousels.count ?? 0) + 1 + (page?.collapsibles.count ?? 0)
to see how many rows your tableview has. Most definitely indexForSecondSetTableViewCells is more than the number of rows
I am trying to use a UITableViewController(Static table view) with 4 sections and each has a different type of cell.
The number of cells in a section depends on the data received from the web service. In the storyboard, I have created one type of cell in each section.
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Number of rows in attachment sect
if section == 2 {
guard let currentDataModel = dataModel else { return 0 }
return currentDataModel.attachments.count
}
else if section == 3 {
guard let currentDataModel = dataModel else { return 0 }
return currentDataModel.contacts.count
}
return super.tableView(tableView, numberOfRowsInSection: section)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let currentSection = indexPath.section
if currentSection == 2 {
let currentRow = indexPath.row
let cell = tableView.dequeueReusableCell(withIdentifier: "attachmentCell", for: indexPath) as! AttachmentViewCell
cell.setDataForCell(dataModel: dataModel?.attachments[currentRow], indexPath: indexPath)
return cell
}
//Show cells for Contact Section
else if currentSection == 3 {
let currentRow = indexPath.row
let cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath) as! ContactViewCell
cell.setDataForCell(dataModel: dataModel?.contacts[currentRow], indexPath: indexPath)
return cell
}
return super.tableView(tableView, cellForRowAt: indexPath)
}
I am getting this error while calling dequeueReusableCellWithIdentifier:forIndexPath:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1]'
Can I Use the different type of cells and a different number of rows in each section in a UITableViewController?
Can you try this.If need a four sections then return 4 in numberofsections. You can add the title to each sections as below and later add it to label in viewForHeaderInSection.You must provide the number of rows in each sections correctly.
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 4
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if(section == 0)
{
return "Section 0"
}
else if(section == 1)
{
return "Section 1"
}
else if(section == 2)
{
return "section 2"
}
else if(section == 3)
{
return "section 3"
}
return ""
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
switch(section)
{
case 0: //for first section
//return your count
case 1://Cells for
//return your count
case 2:
//return your count
case 3:
//return your count
default:
return 4
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! Cell1
return cell
}
else if indexPath.section == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! Cell1
return cell
}
else if indexPath.section == 2 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! Cell1
return cell
}
else if indexPath.section == 3 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! Cell1
return cell
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as? Cell2
//Set up labels etc.
return cell!
}
}
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 50))
headerView.layer.borderWidth = 2
let myLabel = UILabel()
myLabel.frame = CGRectMake(0, 0, tableView.frame.width - 70, 50)
myLabel.font = UIFont.boldSystemFontOfSize(18)
myLabel.textColor = UIColor.whiteColor()
myLabel.textAlignment = .Left
myLabel.text = " " + self.tableView(tableView, titleForHeaderInSection: section)!
headerView.addSubview(myLabel)
return headerView
}
If you are using .xib file then you should also register that file in viewDidLoad() as
self.tableView.registerNib(UINib(nibName: "cell1", bundle: nil), forCellReuseIdentifier: "cell1")
self.tableView.registerNib(UINib(nibName: "cell2", bundle: nil), forCellReuseIdentifier: "cell2")