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
Related
Ok so I am geting memory errors from this which is annoying ,since it isn't something like a simple syntax error. Well the thing I am doing to understanding how to manipulate data
What I am trying to do is to allow it to delete from another view ,but the thing still crashes. I will share the two table views I got going on.
This is the one that has problems ,since it is in the second view controller
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return FeedCommands.commentSection.count
}
//allows us to delete the code
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// this is called from a static variable class function
FeedCommands.RemoveComment(atIndex: indexPath.row)
CommentFeed.deleteRows(at: [indexPath], with: .fade)
}
}
Now this is the one that works perfectly fine
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return FeedCommands.feedArray.count
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
FeedCommands.feedArray.remove(at: indexPath.row)
TabView.deleteRows(at: [indexPath], with: .fade)
}
}
If I ran the problem one it exits with a memory error, I am thinking that it might have to deal with the arrays and might be the actual cause. I searched and there doesn't really seem to be anything that covers this case when doing multiple tableviews.
Here is the class I am calling the arrays from
static var commentSection: Array<String> = []
class func AddToComment(newElement: String){
FeedCommands.commentSection.append(newElement)
}
class func RemoveComment (atIndex: Int){
FeedCommands.commentSection.remove(at: atIndex)
}
static var QuestionToComment: Array<String> = []
class func AddQuestionToComment(newElement: String){
FeedCommands.QuestionToComment.append(newElement)
}
class func RemoveQuestionToComment (atIndex: Int){
FeedCommands.QuestionToComment.remove(at: atIndex)
}
static var feedArray: Array<String> = []
class func AddToFeed (newElement: String){
FeedCommands.feedArray.append(newElement)
}
class func Remove (atIndex: Int){
FeedCommands.feedArray.remove(at: atIndex)
}
If it needs more details please let me know.
Edit: Due to a request
this is the comment section file
import UIKit
class Comments: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var Question: UITextView!
#IBOutlet weak var ReplyTextField: UITextField!
#IBOutlet weak var CommentFeed: UITableView!
#IBAction func SubmitReply(_ sender: UIButton) {
CommentFeed.reloadData()
if ReplyTextField.text == nil {
}
else{
FeedCommands.AddToComment(newElement: ReplyTextField.text!)
ReplyTextField.text = ""
}
// dismiss(animated: true, completion: nil)
// ReplyTextField.placeholder = "Comment"
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
//this is what we use to get the question to
//appear in the comment section
Question.text = ""
for Section in FeedCommands.QuestionToComment{
Question.text = "\(Section)"
CommentFeed.reloadData()
}
}
//adding the table view
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return FeedCommands.commentSection.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = CommentFeed.dequeueReusableCell(withIdentifier: "Com", for: indexPath)
cell.textLabel?.text = "#\(Question.text!)__ \(FeedCommands.commentSection[indexPath.row])"
return cell
}
//allows us to delete the code
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
FeedCommands.commentSection.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade) // crashes here
}
}
}
You are reloading the table view data before appending a new element to your table view instead of reloading it after appending the reply. Thats why you needed to press your button twice to make it appear. What you should actually do to fix your submit reply action is to insert a new row at the last index (count - 1) of your table view every time the SubmitReply button is pressed:
#IBAction func SubmitReply(_ sender: UIButton) {
if !ReplyTextField.text!.isEmpty{
FeedCommands.AddToComment(newElement: ReplyTextField.text!)
ReplyTextField.text = ""
CommentFeed.insertRows(at: [IndexPath(row: FeedCommands.commentSection.count-1, section: 0)], with: .automatic)
}
}
I search already a few days to the answer on the question how can I save the reorder TableView with Swift? So many tutorials on the internet show how to reorder but not how to save with UserDefaults.
This is my code right now. What do I wrong?
Please can you help me to the solution? Thank you very much.
import UIKit
class soundboardTableViewController: UITableViewController {
var list = ["January","February","March","April","May","June", "July","August","September","October","November", "December"]
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.rightBarButtonItem = self.editButtonItem
let blockItems = UserDefaults.standard.object(forKey:"soundboard")
if(blockItems != nil) {
list = blockItems as! [String]
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return list.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = list[indexPath.row]
return cell
}
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
/* Override to support editing the table view.*/
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
list.remove(at: indexPath.row)
UserDefaults.standard.set(self.list, forKey:"soundboard")
UserDefaults.standard.synchronize()
tableView.reloadData()
}
}
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt indexPath: IndexPath, to: IndexPath) {
let itemToMove = list[indexPath.row]
list.remove(at: indexPath.row)
list.insert(itemToMove, at: indexPath.row)
UserDefaults.standard.set(self.list, forKey:"soundboard")
UserDefaults.standard.synchronize()
}
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
if(self.isEditing) {
}
}
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
}
Your code in tableView(_:moveRowAt:to:) has some errors. You should change it to:
override func tableView(_ tableView: UITableView, moveRowAt indexPath: IndexPath, to: IndexPath) {
let itemToMove = list[indexPath.row]
list.remove(at: indexPath.row)
list.insert(itemToMove, at: to.row)
UserDefaults.standard.set(self.list, forKey:"soundboard")
}
Notice that I removed UserDefaults.standard.synchronize(). You should remove it from your other methods as well, since it is kind of a non-sense in this case. I have also changed list.insert(itemToMove, at: indexPath.row) to list.insert(itemToMove, at: to.row), because you need to place it to the "destination" index, and not put it back from where you removed it.
The rest of your code seems fine. It should be working once you perform these changes.
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.
I get this error when I actually run the code (this line is the problem var cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(CellId) as UITableViewCell. THis is in a UITableViewController class.
import UIKit
class AlarmsTableViewController: UITableViewController {
var myData:Array<AnyObject> = []
override func viewDidLoad() {
myData = ["one", "two", "three", "four"]
}
override func didReceiveMemoryWarning() {
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellId:String = "Cell"
var cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(CellId) as UITableViewCell
//if let ip = indexPath {
cell.textLabel?.text = myData[indexPath.row] as? String
//}
return cell
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
//Delete row from data source
//if let tv = tableView? {
myData.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
}
}
}
In the interface builder, select the TableViewController with which you are working with. Then, select the prototype cell and set its style to "Basic". Finally, set the cells reuse identifier to Cell.
I'm making a to-do list app but when I try to delete something from my list, xcode is giving me an error that says "fatal error: array index out of range". Can someone tell me what I'm doing wrong with my array that is causing this to happen?
import UIKit
class SecondViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
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 tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return eventList.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
cell.textLabel?.text = eventList[indexPath.row]
return cell
}
override func viewWillAppear(animated: Bool) {
if var storedEventList : AnyObject = NSUserDefaults.standardUserDefaults().objectForKey("EventList") {
eventList = []
for var i = 0; i < storedEventList.count; ++i {
eventList.append(storedEventList[i] as NSString)
}
}
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if(editingStyle == UITableViewCellEditingStyle.Delete) {
eventList.removeAtIndex(indexPath.row)
NSUserDefaults.standardUserDefaults().setObject(eventList, forKey: "EventList")
NSUserDefaults.standardUserDefaults().synchronize()
}
}
}
A breakpoint saying EXC_BAD_INSTRUCTION is being created at the eventList.removeAtIndex(indexPath.row)as well.
It is not sufficient to remove the item from the data source array.
You also have to tell the table view that the row is deleted:
if editingStyle == .Delete {
eventList.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
// ...
}
Otherwise the table view will call the data source methods for the original
number of rows, causing the out of range error.
Alternatively, you can call tableView.reloadData() when modifying the data source, but the above method
gives a nicer animation.
It means you are trying to access an index,indexPath.row, that exceed the eventList range. To fix this issue try:
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if(editingStyle == .Delete && indexPath.row < eventList.count) {
eventList.removeAtIndex(indexPath.row)
tableView.reloadData()
NSUserDefaults.standardUserDefaults().setObject(eventList, forKey: "EventList")
NSUserDefaults.standardUserDefaults().synchronize()
}
}