class showPageViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
{
#IBOutlet weak var tableView: UITableView!
var records : [Record] = []
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return records.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
return cell
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath){
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
if editingStyle == .delete{
let record = records[indexPath.row]
context.delete(record)
(UIApplication.shared.delegate as! AppDelegate).saveContext()
do{
records = try context.fetch(Record.fetchRequest())
} catch{
print("Failed")
}
}
}
override func viewWillAppear(_ animated: Bool) {
getData()
tableView.reloadData()
}
func getData(){
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do{
records = try context.fetch(Record.fetchRequest())
} catch{
print("123")
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Hello everyone, I just tried to show the core data in table view, I already connect the dataSource and delegate to the ViewController, and I confirmed There are some data in core data, anyone can help me plz? thanks
Two big mistakes:
You cannot create a cell with the default initializer UITableViewCell() you have to dequeue it.
You have to get the item in the data source array for the index path and assign a value of a property to a label of the cell.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let record = records[indexPath.row]
cell.textLabel!.text = record.<nameOfProperty>
return cell
}
cell is the identifier specified in Interface Builder.
<nameOfProperty> is a property in your data model.
Related
Im trying to load a array of strings in a table view but the view does not recognize the array.
I have an array called Playlists (declared as global on ThirdViewController) with objects from class Playlist. When I use it on every other table view I can access every object and use it on the table view (I'm using it on ThirdViewController), but on AddToPlaylist view I can't use it. I think I'm using correctly the cells and func for table views.
This happens when I press the button "AƱadir" on player view. It should load the table view with the array info.
Here is the project (develop branch): tree/develop
import UIKit
class AddToPlaylist: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var myTableViewPlaylist: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Playlists.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "hola", for: indexPath)
cell.textLabel?.text = Playlists[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
Playlists[indexPath.row].songs.append(songName)
performSegue(withIdentifier: "addedSong", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
myTableViewPlaylist.delegate = self
myTableViewPlaylist.dataSource = self
myTableViewPlaylist.reloadData()
}
}
Here is the declaration of Playlists array:
import UIKit
import AVFoundation
var favorites:[String] = []
var Playlists:[Playlist] = []
var selecPlaylist = 0
var firstOpen2 = true
class ThirdViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var myTableView2: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//print(Playlists.count)
return Playlists.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = Playlists[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selecPlaylist = indexPath.row
performSegue(withIdentifier: "segue", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
myTableView2.delegate = self
myTableView2.dataSource = self
if firstOpen2{
crear()
firstOpen2 = false
}
myTableView2.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func crear(){
let pl1 = Playlist(name: "Prueba")
pl1?.addSong(song: songs[0])
Playlists.append(pl1!)
let pl2 = Playlist(name: "Prueba2")
pl2?.addSong(song: songs[1])
Playlists.append(pl2!)
}
}
let cell = tableView.dequeueReusableCell(withIdentifier: "yourIdentifier") as! UITableViewCell
cell.textLabel?.text = Playlists[indexPath.row].name
return cell
i have a tableview in a viewcontroller and because i need to reuse most of the code for another table i created an extra class:
class StatisticsViewDelegate: NSObject, UITableViewDelegate, UITableViewDataSource {
var defaultList:[String]
var infolist:[String] = []
var tableView:UITableView
var controller:UIViewController?
init(defaultList:[String], view:UITableView, controller:UIViewController?) {
self.defaultList = defaultList
self.controller = controller
tableView = view
super.init()
tableView.delegate = self
tableView.dataSource = self
loadTable()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return infolist.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "infocell", for: indexPath) as! TableViewCell
// [fill cell]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// [...]
}
func loadTable() {
DispatchQueue.global(qos: .userInitiated).async {
//[...]
// in this case:
self.infolist = self.defaultList
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
}
and in my UITViewController in the viewDidLoad():
delegate = StatisticsViewDelegate(defaultList: defaultList, view: tableView, controller:self)
delegate is a member of the ViewController
now when i run it, the function func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) never gets called. The func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) gets called however(before and after the reload) and returns the correct number(in my case 4). The TableView isn't visible at all. Where is my error?
Maybe you can use the subclassing strategy to resolve your problem. There are many reference passed to your class and if you forgot to clean that up you will be have memory leaks in your hand. So I'll suggest the simple example as below. You can modify as you like and let me know if that was what you are after. If not please pardon me.
//This will be parent class that will handle all table methods, so you need to write only once the delegates and stuffs
class MyCommonTableController: UITableViewController {
var infoList = [String]()
// MARK: - TableView Delegate and Datsource Impl
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return infoList.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 55.0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = infoList[indexPath.row]
return cell
}
}
The first class that is directly subclassing the from above MyCommonTableController
//In here we just have to know the data and set the infoList from parent
class TheTableViewController: MyCommonTableController {
let defaultList = ["Data1","Data2","Data3"] //....etc
override func viewDidLoad() {
super.viewDidLoad()
//this is were I will set those
infoList = defaultList
//reload the table
tableView.reloadData()
}
}
The second class that is directly subclassing the from above MyCommonTableController. Same process goes here
class TheSecondTableViewController: MyCommonTableController {
let defaultList = ["List1","List2","List3"] //....etc
override func viewDidLoad() {
super.viewDidLoad()
//this is were I will set those
infoList = defaultList
//reload the table
tableView.reloadData()
}
}
And now you are not repeating and table methods. You can also get the reference of table and use in your norma table view
#IBOutlet weak var theTable: UITableView!
let defaultList = ["List1","List2","List3"] //....etc
let commonTable = MyCommonTableController()
// MARK: - LifeCycle
override func viewDidLoad() {
super.viewDidLoad()
commonTable.infoList = defaultList
commonTable.tableView = theTable
}
This is the code I have so far. I am able to enter into the textfield and have it appear in the UITableView, but only after I reload the page and come back to it. I want for what I enter into the textfield and when I click 'add' for it to automatically appear in the UITableView.
#IBOutlet var itemTextField: UITextField!
#IBOutlet var table: UITableView!
var items: [String] = []
#IBAction func add(_ sender: Any) {
let itemsObject = UserDefaults.standard.object(forKey: "items")
var items:[String]
if let tempItems = itemsObject as? [String] {
items = tempItems
items.append(itemTextField.text!)
print(items)
} else {
items = [itemTextField.text!]
}
UserDefaults.standard.set(items, forKey: "items" )
itemTextField.text = ""
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
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: "cell")
cell.textLabel?.text = items[indexPath.row]
cell.textLabel?.font = UIFont(name: "Type02", size: 20)
return cell
}
override func viewDidAppear(_ animated: Bool) {
let itemsOBject = UserDefaults.standard.object(forKey: "items")
if let tempItems = itemsOBject as? [String]{
items = tempItems
}
table.reloadData()
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCellEditingStyle.delete {
items.remove(at: indexPath.row)
table.reloadData()
UserDefaults.standard.set(items, forKey: "items")
}
}
You need to tell the table view to reloadData() whenever the items array changes. So try adding table.reloadData() to the end of your add function.
It works for me .
Add outlet for textfield and tableview.
#IBOutlet weak var nametextField: UITextField!
#IBOutlet weak var dataTableView: UITableView!
Add IBAction for Add action button.
#IBAction func addNameToTable(_ sender: Any) {
// Check for value in nameTextField
guard let profilename = nametextField.text else{
return
}
// Append text field value in data array
data.append(profilename)
// Reload table to show text field name in table
dataTableView.reloadData()
}
Create array to hold string values-:
var data = [String]()
Add table methods to populate data on table on clicking Add button.
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}// Default is 1 if not implemented
// return array count
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return data.count
}
// dequeue cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
cell.textLabel?.text = data[indexPath.row]
return cell
}
// Row height
public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{
return 50
}
COMPLETE CODE -:
import UIKit
import AVKit
class ViewController: UIViewController {
#IBOutlet weak var nametextField: UITextField!
#IBOutlet weak var dataTableView: UITableView!
var data = [String]()
//MArk-: ViewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func addNameToTable(_ sender: Any) {
guard let profilename = nametextField.text else{
return
}
data.append(profilename)
dataTableView.reloadData()
}
}
extension ViewController : UITableViewDelegate,UITableViewDataSource{
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}// Default is 1 if not implemented
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
cell.textLabel?.text = data[indexPath.row]
return cell
}
public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{
return 50
}
}
Everything works, except when I click on a row.. nothing happens it should output You selected cell number:
class JokesController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var jokes_list: UITableView!
var CountCells = 0
var CellsData = [[String: Any]]()
override func viewDidLoad() {
super.viewDidLoad();
Alamofire.request("http://localhost:8080/jokes.php").responseJSON{ response in
if let JSON = response.result.value as? [[String: Any]] {
self.CellsData = JSON
self.CountCells = JSON.count
self.jokes_list.reloadData()
}else{
debugPrint("failed")
}
}
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return CellsData.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
cell.textLabel?.text = CellsData[indexPath.row]["title"] as! String?
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
debugPrint("You selected cell number: \(indexPath.row)!")
}
}
First, you need to inherit from UITableViewDelegate (class ... : UIViewController, UITableViewDelegate.. ).
Then, you need to assign
self.jokes_list.delegate = self
self.jokes_list.dataSource = self
tentatively in your viewDidLoad.
Edit: As #zsteed mentioned.
class showPageViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var records : [Record] = []
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return records.count
}
func tableview(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
func tableView(_ tableVoew: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath){
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
if editingStyle == .delete{
let record = records[indexPath.row]
context.delete(record)
(UIApplication.shared.delegate as! AppDelegate).saveContext()
do{
records = try context.fetch(Record.fetchRequest())
} catch{
print("Failed")
}
}
}
override func viewWillAppear(_ animated: Bool) {
getData()
tableView.reloadData()
}
func getData(){
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do{
records = try context.fetch(Record.fetchRequest())
} catch{
print("123")
}
}
}
This is the code of my program, I am trying to make a to-do list app, but the error does not confirm to protocol "UITableViewDataSource" always appear, I try to find the solution, but nothing suitable for me, is anyone can help me? thanks
You have a mix of Swift 2 and Swift 3 methods in your code. Your cellForRow... method is using the newer Swift 3 signature. You need to use the older Swift 2 compatible version.
I believe it is:
func tableview(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
}
Check all of the other table view data source and delegate methods and make sure they all use the Swift 2 compatible signatures and not the newer Swift 3 signatures.
Yes, You are mixing swift 2 and swift 3. Your methods should be like this:
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
// Configure the cell...
return cell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
You have done several spelling mistakes in those methods, Please check above methods with yours