How to link delegate and datasource to multiple tableviews in one ViewController? - ios

I created two UITableView inside a UIViewController. To link to the delegate and datasource I used the basic method, holding Ctrl and dragging to the "yellow ball" above. However, I can only do this with one, when each UITableView should separately have its own database in the class. When I do the same with the second UITableView, it apparently links the same datasource and delegate to both, without extracting the data from the class to the second and displaying them on the screen.
How can I fix that?
//I declared four buttons, two in each table view.
#IBOutlet weak var btnDrop: UIButton!
#IBOutlet weak var tblView: UITableView!
#IBOutlet weak var btnDropProj: UIButton!
#IBOutlet weak var tblViewProj: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tblView.isHidden = true
tblViewProj.isHidden = true
}
var selectClient = ["Cliente 1", "Cliente 2", "Cliente 3", "Cliente 4", "Cliente 5", "Cliente 6", "Cliente 7", "Cliente 8"]
var selectProject = ["Projeto 1", "Projeto 2", "Projeto 3", "Projeto 4", "Projeto 5", "Projeto 6", "Projeto 7", "Projeto 8"]

It seems to me that you are trying to link your table views to 2 different data sources.
You can do that by first creating 2 separate data sources like below.
class Table1DataSource: NSObject, UITableViewDataSource {
// Properties
private var table1Data: [String]
init(table1Data: [String]) {
self.table1Data = table1Data
super.init()
}
// MARK: - Data Source
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.table1Data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var profileCell: ProfileCell
let cell = tableView.dequeueReusableCell(withIdentifier: Table1Cell.reuseIdentifier, for: indexPath) as! Table1Cell
// Initialize the cell here
return cell
}
}
After that you can link the data source to your table view in your controller.
class MainController: UIViewController {
// Outlets
#IBOutlet weak var tblView: UITableView!
#IBOutlet weak var tblViewProj: UITableView!
// Properties
var selectClient = ["Cliente 1", "Cliente 2", "Cliente 3", "Cliente 4", "Cliente 5", "Cliente 6", "Cliente 7", "Cliente 8"]
var selectProject = ["Projeto 1", "Projeto 2", "Projeto 3", "Projeto 4", "Projeto 5", "Projeto 6", "Projeto 7", "Projeto 8"]
// DataSource
lazy var tblViewDataSource: Table1DataSource = {
return Table1DataSource(table1Data: self.selectClient)
}()
override func viewDidLoad() {
super.viewDidLoad()
self.tblView.dataSource = self.tblViewDataSource
}
}
All that's left to do is to repeat the steps to link your second table.
Hope it helps!

// MARK: - UITableView datasource
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.tblView {
return selectClient.count
}
else {
return selectProject.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
if tableView == self.tblView {
let CellIdentifier: String = "YOURCUSTOMCELL"
var cell: YOURCUSTOMCELL? = (tableView.dequeueReusableCell(withIdentifier: CellIdentifier) as? YOURCUSTOMCELL)
if cell == nil {
let topLevelObjects: [Any] = Bundle.main.loadNibNamed("YOURCUSTOMCELL", owner: nil, options: nil)!
cell = (topLevelObjects[0] as? YOURCUSTOMCELL)
cell?.selectionStyle = .none
}
cell?.backgroundColor = UIColor.white
return cell!
}
else {
let CellIdentifier: String = "YOURCUSTOMCELL"
var cell: YOURCUSTOMCELL? = (tableView.dequeueReusableCell(withIdentifier: CellIdentifier) as? YOURCUSTOMCELL)
if cell == nil {
let topLevelObjects: [Any] = Bundle.main.loadNibNamed("YOURCUSTOMCELL", owner: nil, options: nil)!
cell = (topLevelObjects[0] as? YOURCUSTOMCELL)
cell?.selectionStyle = .none
}
cell?.backgroundColor = UIColor.white
return cell!
}
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if tableView == self.tblView {
return 50.0
}
else {
return 50.0
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView == self.tblView {
}
else {
}
}

Related

Show button if cell is tapped and hide after leave in UITableView

If someone taps over the cell or selects the cell then the button will show or else it'll be hidden. Only that cell that is playing the current song will show the button (it's for either play or stop) but the problem is the button shown on each row of the cell if didn't hide it also I don't want to hide the button if I click the playing song cell again.
class AudioListViewController: UIViewController {
var selectedRowIndex = -1
var songList: [Audio] = [
Audio(id: 0, trackName: "Song 1", trackTitle: "ABbcd:", album: "Loreim loreim",
uploadedBy: "A men", genre: "Romantic", lyricsLang: "English", artist: "God",
duration: 2.00),
Audio(id: 1, trackName: "Song 2", trackTitle: "ABbcd:", album: "Loreim loreim",
uploadedBy: "A men", genre: "Romantic", lyricsLang: "English", artist: "God",
duration: 2.00),
Audio(id: 2, trackName: "Song 3", trackTitle: "ABbcd:", album: "Loreim loreim",
uploadedBy: "A men", genre: "Romantic", lyricsLang: "English", artist: "God",
duration: 2.00)
]
#IBOutlet weak var songListTableView: UITableView!
var isTapped: Bool = false
#IBOutlet weak var close: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
songListTableView.dataSource = self
songListTableView.delegate = self
songListTableView.register(UINib(nibName: "SongsListTableViewCell", bundle: nil),
forCellReuseIdentifier: "SongListCell")
}
}
extension AudioListViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return songList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SongListCell",
for: indexPath) as! SongsListTableViewCell
cell.songTitle?.text = songList[indexPath.row].trackName
cell.songDuration?.text = String(songList[indexPath.row].duration)
return cell
}
}
extension AudioListViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let position = indexPath.row
let vc = tableView.dequeueReusableCell(withIdentifier: "SongListCell",
for: indexPath) as! SongsListTableViewCell
}
}
My UITableViewCell code:
class SongsListTableViewCell: UITableViewCell {
public var position: Int = 0
public var isPlaying: Bool = false
var cellsState: Bool = false
#IBOutlet weak var singleViewCell: UIStackView!
#IBOutlet weak var songCellView: UIView!
#IBOutlet weak var songImage: UIImageView!
#IBOutlet weak var songTitle: UILabel!
#IBOutlet weak var songDuration: UILabel!
#IBOutlet weak var makeFavorite: UIButton!
#IBOutlet weak var useSong: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
useSong.addTarget(self, action: #selector(SongsListTableViewCell.selectSong(_:)), for: .touchUpInside)
makeFavorite.addTarget(self, action: #selector(SongsListTableViewCell.makeFavourite(_:)), for: .touchUpInside)
useSong.isHidden = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
useSong.layer.cornerRadius = 6
}
#IBAction func makeFavourite(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
makeFavorite.setImage(UIImage(systemName: "star.fill"), for: .normal)
} else {
makeFavorite.setImage(UIImage(systemName: "star"), for: .normal)
}
}
}
This is how it's looking right now:
This is my Songlistview:
Hello Tyler i am using function in UITableViewDelegate with didSelectRowAt and didDeselectRowAt to show and hide , and don't hide why i click the component in Cell , with the function will check row in the index path and call function hide/show
import UIKit
class ShowHideTableviewVC: UIViewController {
#IBOutlet weak var tableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.tableview.dataSource = self
self.tableview.delegate = self
}
}
extension ShowHideTableviewVC: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ShowHideCell", for: indexPath) as! ShowHideCell
return cell
}
}
extension ShowHideTableviewVC: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? ShowHideCell {
cell.showButton(show: true)
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? ShowHideCell {
cell.showButton(show: false)
}
}
}
and this is the code in the cell it will hide the button component and make the height zero because we want hide the button component
import UIKit
class ShowHideCell: UITableViewCell {
#IBOutlet weak var buttonx: UIButton!
#IBOutlet weak var heightButton: NSLayoutConstraint!
override func awakeFromNib() {
super.awakeFromNib()
showButton(show: false)
}
func showButton(show: Bool) {
if show {
heightButton.constant = 30
buttonx.isHidden = !show
} else {
heightButton.constant = 0
buttonx.isHidden = !show
}
}
}
it will not hide the button (play button) when you click the button component inner cell because it using selected in the UITableViewDelegate

Trouble passing the correct information from a tableview to a new view controller

Right now I have a program that displays different organizations in a tableview. When an organization is selected, then it displays a screen that passes the name of that specific organization. However, the problem is that when I click on "organization 2" of "section 1" I get the results that would be displayed in "organization 1" of "section 1". How would I fix this so that, when I click "organization 2" of "section 1" it displays the correct information?
Here is my code for the first view controller.
import UIKit
struct Organizations {
var sectionTitle = String()
var rowTitles = [String]()
}
class SearchOrganizationsViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var searchOrganizations: Organizations?
var selectedRow = 0
var organizations = [Organizations(sectionTitle: "section 1", rowTitles: ["organization 1", "organization 2", "organization 3"]),
Organizations(sectionTitle: "section 2", rowTitles: ["organization 1", "organization 2"]),
Organizations(sectionTitle: "section 3", rowTitles: ["organization 1"])
]
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
extension SearchOrganizationsViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "searchCell")
cell?.textLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
cell?.textLabel?.numberOfLines = 3
if searching {
cell?.textLabel?.text = self.searchArray[indexPath.section].rowTitles[indexPath.row]
} else {
cell?.textLabel?.text = self.organizations[indexPath.section].rowTitles[indexPath.row]
}
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedOrganizations = organizations[indexPath.section]
performSegue(withIdentifier: "organizationDetailSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? OrganizationsDetailViewController {
destination.organization = selectedOrganizations
destination.selectedRow = selectedRow
}
}
Here is my code for the second view controller.
import UIKit
class OrganizationsDetailViewController: UIViewController {
#IBOutlet weak var organizationNameLabel: UILabel!
var organization: Organizations? = nil
var selecterRow: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
setupLabel()
}
private func setupLabel() {
guard let org = self.organization else { return }
self.organizationNameLabel.text = org.rowTitles[selectedRow]
}
}
Modify your didSelectRow to this to fix your mentioned issue:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedOrganizations = searching ? searchArray[indexPath.section] : organizations[indexPath.section]
selectedRow = indexPath.row
performSegue(withIdentifier: "organizationDetailSegue", sender: self)
}

Error: Cannot assign value of type '[ViewController.organizations]' to type '[(sectionTitle: String, rowTitles: [String])]'

I am trying to implement a search bar into a tableview, but get the error, 'Cannot assign value of type '[ViewController.organizations]' to type '[(sectionTitle: String, rowTitles: [String])]' on the line "searchArray = dataArray.filter({$0.sectionTitle.lowercased().contains(searchBar.text!.lowercased())})". Can someone help me fix this? The ultimate goal is to use the search bar to narrow results of the list. Here is my code.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var tableView: UITableView!
struct data {
var sectionTitle = String()
var rowTitles = [String]()
}
var dataArray = [data(sectionTitle: "section 1", rowTitles: ["row 1", "row 2", "row 3"]),
data(sectionTitle: "section 2", rowTitles: ["row 1"]),
data(sectionTitle: "section 3", rowTitles: ["row 1", "row 3"])
]
var searchArray = [(sectionTitle: String, rowTitles: [String])]()
var searching = false
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searching {
return searchArray[section].rowTitles.count
} else {
return dataArray[section].rowTitles.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "searchCell")
if searching {
cell?.textLabel?.text = self.searchArray[indexPath.section].rowTitles[indexPath.row]
} else {
cell?.textLabel?.text = self.dataArray[indexPath.section].rowTitles[indexPath.row]
}
return cell!
}
func numberOfSections(in tableView: UITableView) -> Int {
return self.dataArray.count
}
}
extension ViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchArray = dataArray.filter({$0.sectionTitle.lowercased().contains(searchBar.text!.lowercased())})
searching = true
tableView.reloadData()
}
}
Change your search array type to data instead of [(sectionTitle: String, rowTitles: [String])]()
var searchArray = [Data]()
struct Data {
var sectionTitle = String()
var rowTitles = [String]()
}
As per #kamran Suggestion

Sort multiple arrays based on one array for TableView

I have table view and three arrays which values are added to tableview cell. I would like to sort nearbyName and nearbyAddress based on nearbyDistance asc. Currently arrays looks like this:
nearbyName = ["Place 1", "Place2", "Place3"]
nearbyAddress = ["Address 1", "Address 2", "Address 3"]
nearbyDistance = [71.00, 50.02, 73.06]
I need to sort them and get result
nearbyName = ["Place 2", "Place1", "Place3"]
nearbyAddress = ["Address 2", "Address 1", "Address 3"]
nearbyDistance = [50.02, 71.00, 73.06]
In future i will get this arrays from JSON so i need to sort them automatically. Full code bellow
import UIKit
import Foundation
class NearbyController: UIViewController, UITableViewDataSource, UITableViewDelegate{
#IBOutlet weak var tableView: UITableView!
let nearbyName = ["Place 1", "Place2", "Place3"]
let nearbyAddress = ["Address 1", "Address 2", "Address 3"]
let nearbyDistance = [71.00, 50.02, 73.06]
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return nearbyName.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellNearby") as! NearbyCell
cell.nearbyClubName.text = nearbyName[indexPath.row]
cell.nearbyClubAddress.text = nearbyAddress[indexPath.row]
cell.nearbyClubDistance.text = nearbyDistance[indexPath.row]
return cell
}
}

Swift: How to pass array items in tableview

I'm trying to pass array values to a tableview.
# //4 println(items) it prints an array with values to my console. I want to have those results passed in to the tableview. The tableview is working but gets it's value from var list: [String] = ...
How do I get the println(items) in the var list: [String] = ... ?
Thanks!!
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var list: [String] = ["Row One", "Row Two", "Row Three" , "Row Four", "Row Five"]
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
var results = "today"
var subItem = "movie"
// hier moet de opegslagen bioscoop komen die door de gebruiker is opgeslagen als keuze
var cinemaFilter = "Pathé Arena"
// Get the Cinema's from scraper and SwiftyJSON
DataManager.getCinemaDataFromScraperWithSuccess { (ScraperData) -> Void in
let json = JSON(data: ScraperData)
if let itemName = json["results"][results][0][subItem]["text"].stringValue {
println("Film resultaten:")
}
//1
if let itemArray = json["results"][results].arrayValue {
//2
var items = [itemModel]()
//3
for itemDict in itemArray {
var itemName: String? = itemDict[subItem]["text"].stringValue
var itemTime: String? = itemDict["time"]["text"].stringValue
var itemCinema: String? = itemDict["cinema"]["text"].stringValue
if itemCinema == cinemaFilter {
var item = itemModel(name: itemName, time: itemTime, cinema: itemCinema )
items.append(item)
} else {
//println("is niet de ingestelde bioscoop")
}
}
//4
println(items)
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.list.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
cell.textLabel?.text = self.list[indexPath.row]
return cell
}
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
println("You selected cell #\(indexPath.row)!")
}
}
Make items an instance variable of your view controller instead of a local variable, use it in the data source methods, and get rid of list.
You then need to decide what part of an item you want to show in cell.textLabel?.text, name, time, cinema, or some combination.
Instead of var items = [itemModel]() inside the func place it on class lavel so it's an instance. Then change
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count;
}
and the cell method accordingly to use items.

Resources