How to pass multiple data in single tableview - ios

Hello I have two different array data that I need to pass into view controller, my ViewControllers design is the same but the only difference is the data. how can I do that? this is my code
var attendance: [GAttendance]!
var subjectAttendances: [GAttendances]!
// In my A controller
let detailAbsenceVC = DetailAbsenceVC()
detailAbsenceVC.attendance = attendances
self.present(detailAbsenceVC, animated: true)
// In my B controller
let detailVC = DetailAbsenceVC()
detailVC.subjectAttendances = subjectAttendances
self.present(detailVC, animated: true, completion: nil)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return attendance.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: GStudentAbsenceCell.cellID, for: indexPath) as! GStudentAbsenceCell
let attendanceItem = attendance[indexPath.row]
cell.configureCell(attendance: attendanceItem)
return cell
}

If you do not distinguish whether you came from A or B, you just need one arrayto store the data in the DetailAbsenceVC, lets call it detailData:
class DetailAbsenceVC : UIViewController {
var detailData = [GAttendance]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return detailData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: GStudentAbsenceCell.cellID, for: indexPath) as! GStudentAbsenceCell
let attendanceItem = detailData[indexPath.row]
cell.configureCell(attendance: attendanceItem)
return cell
}
}
Then, in the A/B controller, just set the detailData:
// In my A controller
let detailAbsenceVC = DetailAbsenceVC()
detailAbsenceVC.detailData = attendances
self.present(detailAbsenceVC, animated: true)
// In my B controller
let detailVC = DetailAbsenceVC()
detailVC.detailData = subjectAttendances
self.present(detailVC, animated: true, completion: nil)

Related

I cannot change the storyboard when the CollectionView that I defined in the TableView class is selected

I placed a collectionView in the TableViewCell. I have defined a collectionView in the TableViewCell and I want the page to change when the collectionView cell is selected. I didn't. How can I do it?
When the collectionView cell in the TableViewCell is clicked, I can't change the page, it gives such an error.
2022-11-20 21:32:43.793429+0300 project-1[6546:225929] [Presentation] Attempt to present <project_1.ViewController: 0x138307190> on <project_1.ContentViewController: 0x138306c10> (from <project_1.ContentViewController: 0x138306c10>) whose view is not in the window hierarchy.
TableViewCell
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//cell
DispatchQueue.main.async {
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ContentView") as! ContentViewController
vc.modalPresentationStyle = .overFullScreen
vc.pages = self.userDetails
vc.currentIndex = indexPath.row
let vcc = ViewController()
vc.present(vcc, animated: true, completion: nil)
}
}
ViewController
extension ViewController : UITableViewDataSource , UICollectionViewDelegate{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
as! TableViewCell
cell.collectionView.tag = indexPath.section
return cell
}
func tableView (_ tableView: UITableView, heightForRowAt indexpath: IndexPath) -> CGFloat{
return 200
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
}
I tried writing it into func in the Viewcontroller.
i got an error like this
enter image description here

Update tableview row label from another tableview selected row in swift

I have stuck up with an issue where I have a UITableView with a label and button in each row when the button is clicked from a particular row it will navigate to the next view and it has UITableView with a country list, when selected the country it will popup to the previous view and I want to update the country name with selected row, Could someone guide me how to update it. Below is my code. TIA
FirstViewController.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomTableCell
let dict = customData[indexPath.row] as? NSObject
cell.lblTitle.text = "Title"
// cell.lblSubTitle.text = ""
cell.selectedButton.tag = indexPath.row
cell.selectedButton.addTarget(self, action: #selector(buttonClick), for: .touchUpInside)
return cell
}
#objc func buttonClick(sender: UIButton){
let customCell = CountryViewController(nibName: nil, bundle: nil)
self.navigationController?.pushViewController(customCell, animated: true)
}
CountryViewController.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CountryCell", for: indexPath) as! CountryTableCell
cell.lblTitle.text = CountryList[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedCountry = CountryList[indexPath.row]
self.navigationController?.popViewController(animated: true)
}
You can use delegation pattern:
protocol SelectCountry {
func countrySelected(withName countryName: String)
}
in your FirstViewController.swift conform to that protocol
extension FirstViewController: SelectCountry {
func countrySelected(withName countryName: String) {
// Assign country name to your label here
}
in your CountryViewController.swift make a variable called delegate/anyName you want
var delegate: SelectCountry?
in your buttonClick method
customCell.delegate = self
in your CountryViewController in didSelectRowAt method
delegate?.countrySelected(withName: CountryList[indexPath.row])
your label will be updated with country name you selected in CountryViewController.
NOTE: Names are just placeholders here you can use your own names for protocol/methods
First Controller:
"CountrySelectionDelegate" confirm this delegate in your first controller
Next, Pass/Store your FirstViewController cell selection index.
Go to your Country Controller, Select country, Pass it through "func selectedCountry(country: String,index: Int) {}" , Update your custom Data/Array.
Lastly reload your Table view with updated Custom data.
class FirstViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,CountrySelectionDelegate {
#IBOutlet weak var yourFirstTable: UITableView!
var customData = [Details(title: "Title-1", country: ""),Details(title: "Title - 2", country: ""),]
override func viewDidLoad() {
super.viewDidLoad()
}
func selectedCountry(country: String,index: Int) {
self.customData[index].country = country
yourFirstTable.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return customData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! DetailTableCell
let custInfo = customData[indexPath.row]
cell.yourTitleLabel.text = "Title: " + custInfo.title
cell.yourCountryLabel.text = (custInfo.country.count > 0 ? "Country: \(custInfo.country)" : "Country: ---")
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "CountryViewController") as? CountryViewController
nextVC?.selectedIndex = indexPath.row
nextVC?.delegate = self
self.navigationController?.pushViewController(nextVC!, animated: true)
}
}
CountryViewController:
import UIKit
protocol CountrySelectionDelegate {
func selectedCountry(country: String, index:Int)
}
class CountryViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var countryTable: UITableView!
var selectedIndex: Int = 0
let countryList = ["India","USA","UK","Nepal","Bangladesh","Pakistan","Bhutan"]
weak var delegate: CountrySelectionDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return countryList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CountryTableViewCell
cell.countryLabel.text = countryList[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate?.selectedCountry(country: countryList[indexPath.row], index: selectedIndex)
self.navigationController?.popViewController(animated: true)
}
}

Limit the selection on UITableView to 2

How can I do to limit the selection of row in tableview to 2.
I mean I have a tableview with items but the user can select unlimited rows. I want to set to 2 selected row maximum.
I just made a listeSiropsSelected and put items on it, and if this list .count >= 2, display an alert. But the 3rd row is selected even if alert is show.
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("Tableview setup \(listeSirops.count) items")
return listeSirops.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "siropCell", for: indexPath) as? ChoisirSiropTableViewCell else {
fatalError("Unable to dequeue tabacCell")
}
let tabac = listeSirops[indexPath.row]
cell.labelNom.text = tabac.nom
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let sirops = listeSirops[indexPath.row]
if(listeSiropsSelected.count >= 2) {
let alert = UIAlertController(title: "Erreur", message: "Vous ne pouvez choisir que 2 sirops.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in
}))
self.present(alert, animated: true, completion: nil)
} else {
listeSiropsSelected.append(sirops.nom)
print(listeSiropsSelected)
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let sirops = listeSirops[indexPath.row]
let objectToRemove = sirops.nom
listeSiropsSelected.remove(object: objectToRemove)
print(listeSiropsSelected)
}
3 rows selected, message appear but how can remove the 3rd row ?
Implement willSelectRowAt, it prevents the selection of a cell if nil is returned
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
return listeSiropsSelected.count < 3 ? indexPath : nil
}
Delete the alert, it's not needed, the user experience is that the user is not able to select more than 2 cells.
Just add this line under self.present:
tableView.deselectRow(at: indexPath, animated: true)
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
//here
if let selectedRows = tableView.indexPathsForSelectedRows, selectedRows.count > 2, let oldestIndexPath = selectedRows.first {
tableView.deselectRow(at: oldestIndexPath, animated: true)
}
let sirops = listeSirops[indexPath.row]
let objectToRemove = sirops.nom
listeSiropsSelected.remove(object: objectToRemove)
print(listeSiropsSelected)
}

How to get textLabel of selected rows and save to firebase in swift?

I am trying to get the value of the textLabel of the rows I select and save to Firebase. I want when I select multiple rows at once, to store to Firebase Database.
Here is my code.
p.s. I'm new to Swift.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return guestList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "guestListCell", for: indexPath) as! GuestListToTableTableViewCell
let guest: GuestModel
guest = guestList[indexPath.row]
cell.fullNameLabel.text = guest.guestName! + " " + guest.guestFamilyName!
cell.checkedImageView.image = UIImage(named: "unChecked")
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableTableView.deselectRow(at: indexPath, animated: true)
indexArray.append(indexPath.row)
guard let cell = tableView.cellForRow(at: indexPath) as? GuestListToTableTableViewCell else { return }
let name: GuestModel
name = guestList[indexPath.row]
print("\(String(describing: name.guestName))") }
Here is my guest Model
class GuestModel {
var guestName: String?
init(guestName: String?)
self.guestName = guestName }

tableView.dequeueReusableCell opens wrong ViewController

i have an array and i've created a seperate vc for each array item,
tableView.dequeueReusableCell shows wrong vc.
I've read that this is because the cell is reusable and it keeps the data from the previous selected array.
Can you please help me to fix it.
My code is:
import UIKit
class Nicosia: UIViewController, UITableViewDelegate, UITableViewDataSource {
let nicosiaPlaces = ["Famagusta Gate", "Laiki Geitonia", "Ledra Street","Omeriye Hamam","Cyprus Museum","Venetian Walls","The House of Hatjigeorgakis Kornessios","Byzantine Art Museum","Archbishop's Palace","Liberty Monument","The Faneromeni Church","Nicosia International Conference Center"]
var identities = ["Famagusta Gate", "Laiki Geitonia", "Ledra Street","Omeriye Hamam","Cyprus Museum","Venetian Walls","The House of Hatjigeorgakis Kornessios","Byzantine Art Museum","Archbishop's Palace","Liberty Monument","The Faneromeni Church","Nicosia International Conference Center"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return nicosiaPlaces.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
let city = nicosiaPlaces [indexPath.row]
cell?.textLabel?.text = city
return cell!
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let vcName = identities[indexPath.row]
let viewController = storyboard?.instantiateViewController(withIdentifier: vcName)
self.navigationController?.pushViewController(viewController!, animated: true)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
}
You mean didDeselectRowAt, not dequeueReusableCell.
And the problem is that you want didSelectRowAt, not didDeselectRowAt.
Replace this
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath)
with
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

Resources