using custom swift class (not main ViewController)
Code:
import Foundation
class Myclass: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tableView: UITableView!
var items: [String] = ["Item1", "Item2", "Item3"]
override func viewDidLoad() {
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "td")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "td")! as UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
return cell
}
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
print("You selected cell #\(indexPath.row)!")
}
}
The correct syntax for the protocol functions in Swift 3 (resolves error):
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "td")
cell.textLabel?.text = items[indexPath.row]
return cell
}
Your method doesn't match the protocol. In swift 3 the protocol methods are different. Verify that they match.
Related
I am working on an app in which I need to show multiple rows with a header. In my case only one section is showing. I have searched everything but can't find a suitable solution.
Here is my code:
class Timeline: UITableViewCell {
#IBOutlet weak var timelineData: UITextView!
}
class StudenTimelineViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let section = ["pizza", "deep dish pizza", "calzone"]
let items = [["Margarita", "BBQ Chicken", "Peproni"], ["sausage", "meat lovers", "veggie lovers"], ["sausage", "chicken pesto", "prawns & mashrooms"]]
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items[section].count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return section.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.section[section]
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TimelineId", for: indexPath) as! Timeline
let gpsData = items[indexPath.section][indexPath.row]
cell.timelineData.text = gpsData
return cell
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 40
}
What I am getting
How will I get all the sections. Thanks in advance.
This is because your method name func numberOfSectionsInTableView(tableView: UITableView) -> Int is incorrect and hence not called.
Replace the name with func numberOfSections(in tableView: UITableView) -> Int and see the magic happen.
//MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewCell", for: indexPath)
cell.selectionStyle = UITableViewCellSelectionStyle.none
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat
{
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let cell: UITableViewCell
cell = tableView.dequeueReusableCell(withIdentifier: "tableviewHeader")!
cell.selectionStyle = UITableViewCellSelectionStyle.none
cell.backgroundColor = UIColor.white
return cell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 32;
}
I tried to use the accessoryButton of the UITableViewCell as the anchor of a Popover, but couldn't connect it using the storyboard. Programmatically I tried using the accessoryButtonTappedForRowWith function, this didn't work either. How can I connect it?
If your class is subclass of UITableViewController then use:
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
print(indexPath.row)
}
Check example code:
class ViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "\(indexPath.row)"
cell.accessoryType = UITableViewCellAccessoryType.detailButton
return cell
}
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
print(indexPath.row)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
}
And if it's a subclass of UIViewController then you don't need override before that method so it will be:
func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
print(indexPath.row)
}
And don't forget to connect UITableViewDataSource and UITableViewDelegate of your table view with your ViewController in this case.
Please help, I'm at my wit's end. I've followed multiple tutorials, read every thread similar to this I can find, and five hours later, I'm still lost and getting the same error: "type ViewController doesn't conform to UITableViewDataSource."
Code:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var proTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
proTable.reloadData()
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return pcMgr.pros.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "Default Pros")
cell.textLabel?.text = pcMgr.pros[indexPath.row].name
return cell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath){
if (editingStyle == UITableViewCellEditingStyle.delete){
pcMgr.pros.remove(at: indexPath.row)
proTable.reloadData()
}
}
}
}
Replace your code with this , you have used old syntax that to inside viewDidLoad function.
import UIKit
class ViewController : UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var proTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
proTable.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "Default Pros")
cell.textLabel?.text = pcMgr.pros[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pcMgr.pros.count
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath){
if (editingStyle == UITableViewCellEditingStyle.delete){
pcMgr.pros.remove(at: indexPath.row)
proTable.reloadData()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
The syntax for the required UITableViewDataSource mehods are not correct.
Try this:
#available(iOS 2.0, *)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
<#code#>
}
#available(iOS 2.0, *)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
<#code#>
}
Because you have already conformed to the protocol, I would recommend using XCode's auto complete on method declarations. Use escape key to see the method declarations.
The correct syntax for the protocol functions in Swift 3
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell ;
return cell
}
Use these methods outside of viewDidLoad method. These methods should be inside your viewDidLoad.
-Remove the functions from viewDidLoad()
-Mention the array
-Add the function "numberOfSections" to the code
hope this helps!
import UIKit
class ViewController: UIViewController , UITableViewDelegate, UITableViewDataSource{
#IBOutlet var proTable: UITableView!
var pcMgr: Array = [] // Or whatever your array is!
override func viewDidLoad() {
super.viewDidLoad()
proTable.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return pcMgr.pros.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "Default Pros")
cell.textLabel?.text = pcMgr.pros[indexPath.row].name
return cell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath){
if (editingStyle == UITableViewCellEditingStyle.delete){
pcMgr.pros.remove(at: indexPath.row)
proTable.reloadData()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Im really new to Swift, the question is how can I represent values from array in label.
I want a TableView with cells dynamically represent values from array into the labels which will be created in tableView rows.
import UIKit
import Foundation
class TableViewMarketItemsViewCell: UITableViewController {
var fruits = ["Avocado", "Apricot", "Pomegranate", "Quince"]
var PriceArray = ["1000 тг.","4000 тг.","3000 тг.","2000 тг."]
var categoryArray = ["Green category","Maroon category","Red category","Yellow category"]
// MARK: - UITableViewDataSource
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fruits.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell", for: indexPath) as! TableViewCell
let fruitName = fruits[indexPath.row]
cell.productTitle.text = fruitName
cell.productImage.image = UIImage(named: fruitName)
return cell
}
}
Thnx in advance
import UIKit
import Foundation
class TableViewMarketItemsViewCell: UITableViewController {
var fruits = ["Avocado", "Apricot", "Pomegranate", "Quince"]
var PriceArray = ["1000 тг.","4000 тг.","3000 тг.","2000 тг."]
var categoryArray = ["Green category","Maroon category","Red category","Yellow category"]
// MARK: - UITableViewDataSource
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fruits.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell", for: indexPath) as! TableViewCell
let fruitName = fruits[indexPath.row]
cell.productTitle.text = fruitName
cell.productImage.image = UIImage(named: fruitName)
cell.productPrice.text = PriceArray[indexPath.row]
cell.productsubTitle.text = categoryArray[indexPath.row]
return cell
}
}
This helped me.
result in picture below:
img
For inserting data into UITableViewcell use below code:
import UIKit
class ViewController: UIViewController,UITableViewDataSource {
#IBOutlet var tableView: UITableView!
var dataArray:NSArray!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.dataSource = self
dataArray = NSArray(objects: "a","b","c")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = dataArray.object(at: indexPath.row) as? String
return cell
}
}
tableView is outlet of UItableView.
You can populate an UITableView from an array like below:
(assuming that your array has a list of string values):
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Creating the tableView cell
let tableViewCell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as! UITableViewCell
//Assigning values
tableViewCell.lblName?.text = array.object(at: indexPath.row) as? String
return tableViewCell
}
In this way you can show the value from your array to the label in your tableView.
import UIKit
class exploreViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var exploreTableView: UITableView!
var CELLHEIGHT = 200
var SECTIONHEADER = "SECTIONHEADER"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
exploreTableView.delegate = self
exploreTableView.dataSource = self
exploreTableView.register(UINib(nibName: "answerCell", bundle: nil), forCellReuseIdentifier: "cell1")
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return SECTIONHEADER
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.exploreTableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! answerCell
cell.name.text = "222222"
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return CGFloat(CELLHEIGHT)
}
}
My numberOfSectionsInTableView is never called and I can't get 2 sections.
From your code, I believe you are using Swift3. Then, the following are delegate and datasource methods for UITableView in Swift3
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
// Configure the cell...
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
As you can see, your numberOfSections function's syntax is wrong.That is the reason.
This is actually due to access level resolution. When we don't specify the "public" ourselves, the compiler resolves it as to be some privately implemented function and even warns that it nearly matches a public function. If one ignores this then it neglects this function and rather calls the default implementation. Hope this helps someone.
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}