Control multiple tableviews in a single view - ios

I have a table view nested in a collection view and i'm returning 3 (possibly more in the future) collection view cells and I was wondering if it is possible to present different content in each one of the collection cells? I attached a few screenshots to better understand what I am taking about. Thanks.
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 3
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
// Configure the cell...
cell.textLabel?.text = "Homeroom"
cell.detailTextLabel?.text = "8:15 AM - 9:00 AM"
cell.selectionStyle = .None
return cell
}

Yes you can. You need set a property for every tableView you have and in delegate method compare it like below
class Some: UIViewController {
var firstTableView: UITableView
var secondTableView: UITableView
override func viewDidLoad() {
firstTableView = YOUR_FIRST
secondTableView = YOUR_Second
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if tableView == firstTableView {
return 2;
}
else if tableView == secondTableView {
return 1;
}
return 3
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if tableView == firstTableView {
return 2;
}
else if tableView == secondTableView {
return 1;
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
if tableView == firstTableView {
cell = tableView.dequeueReusableCellWithIdentifier("cellOfFirstTableView", forIndexPath: indexPath) as! UITableViewCell
}
else if tableView == secondTableView {
cell = tableView.dequeueReusableCellWithIdentifier("cellOfSecondTableView", forIndexPath: indexPath) as! UITableViewCell
}
// Configure the cell...
if tableView == firstTableView {
cell.textLabel?.text = "Homeroom"
cell.detailTextLabel?.text = "8:15 AM - 9:00 AM"
cell.selectionStyle = .None
}
else if tableView == secondTableView {
cell.textLabel?.text = "Homeroom"
cell.detailTextLabel?.text = "8:15 AM - 9:00 AM"
cell.selectionStyle = .None
}
return cell
}
}

You can use UITableViewDelegate / UITableViewDataSource methods with if else conditions or some thing similar
eg.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == table1 { // table1 is a global var for the table
} else if tableView == table2 {
}
}
But I think it will be very clear if you use separate controller class for each table so you can easily manage the code.
But this depends on what type of data you have. If data is completely unrelated you can just use 3 different controllers.
Or if you can reuse data and codes among 3 tables then you can decide if you wanna use 3 different controllers or to use i class with above method.
eg.
let table1Controller = Table1Controller(dataList1)
let table2Controller = Table2Controller(dataList2)
let table3Controller = Table3Controller(dataList3)
table1.delegate = table1Controller
table1.dataSource = table1Controller
table2.delegate = table2Controller
table2.dataSource = table2Controller
table3.delegate = table3Controller
table3.dataSource = table3Controller

Related

TableView cells from different sections getting mixed up

I am trying to implement a tableview with two sections. Each section has one type of cell which will be needed.
So section one cells are subclassed as PendingTVC
section two cells are subclassed as ScheduledCell.
I have the follow methods implemented but the cells are getting mixed up. For example if section one has 3 cells, the first 3 cells in section 2 have a mixed up label which correlates to section one's first 3 cells. Code below:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
if arr != nil {
if section == 0 {
print("returning pending : \(pendingCount)")
return pendingCount
}
else{
print("returning scheduled count : \(scheduledCount)")
return scheduledCount
}
}
return 0
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Pending"
}
else{
return "Scheduled"
}
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50.0
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let data = arr![indexPath.row]
if indexPath.section == 0 {
if let cell = tableView.dequeueReusableCell(withIdentifier: "Pending") as? PendingTVC{
PendingTVC.formattCell(cell: cell, data: data)
cell.selectionStyle = .none;
cell.delegate = self
return cell
}
}
else{
if let cell = tableView.dequeueReusableCell(withIdentifier: "scheduledCell") as? ScheduledCell{
print("cellforrowat in scheduledCell")
ScheduledCell.formatCell(cell: cell, data: data)
cell.selectionStyle = .none;
return cell
}
}
return UITableViewCell()
}
You should fetch your data inside your section condition. If you fetch data beforehand its ambiguous with indexpath data you require.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
if indexPath.section == 0 {
if let cell = tableView.dequeueReusableCell(withIdentifier: "Pending") as? PendingTVC{
let data = pendingarr![indexPath.row] //access pending data here
PendingTVC.formattCell(cell: cell, data: data)
cell.selectionStyle = .none;
cell.delegate = self
return cell
}
}
else{
if let cell = tableView.dequeueReusableCell(withIdentifier: "scheduledCell") as? ScheduledCell{
print("cellforrowat in scheduledCell")
let data = scheduledarr![indexPath.row] // access scheduled arr here
ScheduledCell.formatCell(cell: cell, data: data)
cell.selectionStyle = .none;
return cell
}
}
}
You're using the same data array for for both sections.
let data = arr![indexPath.row]
Here you can see you are referencing indexPath.row as your index within your data array. This means the section is irrelevant. You have at least two options...
Create a 2d array in which the first index value is your section and the second is the row. e.g. dataArray = [[test, test2, test3], [otherTest, otherTest2, otherTest3]]. This can be accessed by changing your line to:
let data = arr![indexPath.section][indexPath.row]
or
2. Create two separate arrays... one for section 1 and one for section 2. Call them within your relevant checks for sections.

Table View not returning data

I'm a student iOS dev, and I'm trying to control a tableview in a collection view cell that is returning 3 (or more) tableviews so I can have multiple tableviews. I believe I implemented everything right but no data is returned to the individual tableviews I have set the reuseidentifiers in the prototype cells in the tableview, and also the delegate and datasource are set to the VC.
var tableView1: UITableView?
var tableview2: UITableView?
// MARK: - Table view data source
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
if tableView == tableView1 {
return 2;
} else if tableView == tableview2 {
return 3
}
return 0;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if tableView == tableView1 {
return 2;
} else if tableView == tableview2 {
return 1;
}
return 0;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
if tableView == tableView1 {
cell = tableView.dequeueReusableCellWithIdentifier("testcell1", forIndexPath: indexPath) as! UITableViewCell
} else if tableView == tableview2 {
cell = tableView.dequeueReusableCellWithIdentifier("testcell2", forIndexPath: indexPath) as! UITableViewCell
}
// Configure the cell...
if tableView == tableView1 {
cell.textLabel?.text = "Homeroom"
cell.detailTextLabel?.text = "8:15 AM - 9:00 AM"
cell.selectionStyle = .None
} else if tableView == tableview2 {
cell.textLabel?.text = "Test Table 2 "
cell.detailTextLabel?.text = "1:30 PM - 2:30 PM"
cell.selectionStyle = .None
}
return cell
}
//**Center collection cells in the middle**
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
let sideInset = (collectionView.frame.size.width - 650) / 2
return UIEdgeInsets(top: 0, left: sideInset, bottom: 0, right: sideInset)
}
}
//Card Scrolling datasource
extension SAHomeViewController: UICollectionViewDataSource {
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
//Number of cards on home screen
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cardcell", forIndexPath: indexPath)
// Configure collection view cell
return cell
}
Here is my project editor to be clearer.
You need to provide default return value in both the functions. Because compiler checking that the functions required Int value should be returned and in these functions if any condition doesn't matched it will not return anything.
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
if tableView == tableView1 {
return 2;
}
else if tableView == tableview2
{
return 3;
}
return 0; // here
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if tableView == tableView1 {
return 2;
} else if tableView == tableview2 {
return 1;
}
return 0; // here
}

Xcode - TableView - Multiple sections

I have multiple sections in my TableView and I'm a bit stuck to display there names in the correct section. I'm new to xcode, so this an easy one for most but not for me :s
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 2
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if section == 0 {
return areas.bars.count
} else {
return areas.clubs.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("barsandclubsIdentifier", forIndexPath: indexPath)
if section == 0 { // **This is where I'm stuck I can't put section -> UITableViewCell**
let bars = areas.bars
let bar = bars[indexPath.row]
cell.textLabel?.text = bar.name
return cell
} else {
let clubs = areas.clubs
let club = clubs[indexPath.row]
cell.textLabel?.text = club.name
}
}
Try this may help you :
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("barsandclubsIdentifier", forIndexPath: indexPath)
if indexPath.section == 0 { // **This is where I'm stuck I can't put section -> UITableViewCell**
let bars = areas.bars
let bar = bars[indexPath.row]
cell.textLabel?.text = bar.name
}else {
let clubs = areas.clubs
let club = clubs[indexPath.row]
cell.textLabel?.text = club.name
}
return cell
}

Hide and Expand UITableView Sections

I am trying to implement a feature where if a user clicks on one of the items in my UICollectionView (that is embedded within a UITableViewCell) it causes another section to appear in the UITableView (below the UICollectionView) with information about that item. I'm having problems with the height of the section that is to appear when clicked. If I set it to 0 initially in heightForRowAtIndexPath there doesn't seem to be a way to alter the cells height later on. I tried giving the cell an initial height then hiding it with cell.hidden but that still leaves the section visible. Maybe there is an alternative way to do this, but after a lot of googling i'm coming up short.
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.section == 3 {
return 90
}
else if indexPath.section == 1 {
return 185
}
else if indexPath.section == 2 {
return 155
}
else if indexPath.section == 4 {
return 100
}
return UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
...
}
else if indexPath.section == 3 {
let cell = tableView.dequeueReusableCellWithIdentifier("weeklyCell", forIndexPath: indexPath) as! WxTableViewCell
cell.selectionStyle = UITableViewCellSelectionStyle.None
cell.forecastCollectionView.delegate = self
cell.forecastCollectionView.dataSource = self
cell.forecastCollectionView.reloadData()
cell.forecastCollectionView.tag = indexPath.row
cell.forecastCollectionView.showsHorizontalScrollIndicator = false
return cell
}
else if indexPath.section == 4 {
let cell = tableView.dequeueReusableCellWithIdentifier("dailyInformation", forIndexPath: indexPath) as! WxTableViewCell
cell.hidden = true
cell.contentView.hidden = true
return cell
}
...
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let index = NSIndexPath(forRow: 0, inSection: 3)
let myindex = NSIndexPath(forRow: 0, inSection: 4)
var myTable = self.tableView
var lastCell = myTable.cellForRowAtIndexPath(index)
var dailyCell = myTable.cellForRowAtIndexPath(myindex)
var myView = UIView(frame: CGRectMake(20, 0, lastCell!.frame.width, lastCell!.frame.height))
dailyCell.frame.size = myView.frame.size
}
Never use indexPath numbers directly to address cells and sections in a switch/case. It's hard to handle when you want add/remove a row/section in the middle. Instead create an enum which have all sections and use an array that contains sections to be shown. You can have cell or section properties like cell identifiers or height in that enum.
enum FileDetailsCell: Printable {
case FileName, Location, Size
var description: String {
switch self {
case .FileName: return "noname"
case .Location: return"Location"
case .Size: return "Size"
}
}
var defaultValue: String {
switch self {
case .Location: return "/"
case .Size: return "Unknown"
default: return ""
}
}
var cellIdentifier: String {
switch self {
case .FileName: return "fileNameCell"
default: return "detailCell"
}
}
}
Here I use description for Cell title. defaultValue for initial value of cell and cellIdentifier is obvious for which purpose.
Then define an array which contains active cells:
var cellsArray: [FileDetailsCell] = [.FileName, .Size]
you can modify this array when you want change visible cells. Now, Location cell is hidden but you can make it visible later only by appending ".Location" to this array and reload tableView.
For tableview delegate:
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellsArray.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellInfo = cellsArray[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier(cellInfo.cellIdentifier, forIndexPath: indexPath) as! UITableViewCell
switch cellInfo {
case .FileName:
cell.textLabel?.text = item.fileName;
case .Location:
cell.textLabel?.text = cellInfo.description
cell.detailTextLabel?.attributedText = item.locationFormatted ?? cellInfo.defaultValue;
case .Size:
cell.textLabel?.text = cellInfo.description
cell.detailTextLabel!.text = item.size ?? cellInfo.defaultValue;
}
return cell
}
In this example I assumed sections are only one to avoid confusion. You can get similar approach for sections.

Xcode: Swift - Table Cell not showing all text

My cells are getting the text fine, but they aren't showing all the text.
Image: http://i.imgur.com/Aql1meS.png
Here is the code for my table view controller:
class ResultsTableViewController: UITableViewController {
var mapItems: [MKMapItem] = [MKMapItem]()
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return mapItems.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("resultCell", forIndexPath: indexPath) as! ResultsTableCell
if(indexPath.row % 2 == 0) {
cell.backgroundColor = UIColor.clearColor()
}else{
cell.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.2)
cell.textLabel?.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.0)
}
// Configure the cell...
let row = indexPath.row
let item = mapItems[row]
cell.nameLabel.text = item.name
cell.phoneLabel.text = item.phoneNumber
return cell
}
}
I've searched around to see if I have a character limit set, but can't seem to find anything. Thanks in advance.
It seems like your UILabels aren't wide enough. If you make them wider, (or apply auto layout on all 4 sides, well... that gets more complicating,) then it should work fine.
Hope this helps!!

Resources