Iv been trying to add userDefaults to my code and trying to save for example a task so the next time i open the app i can still see the task .
didnt quit understood how userDefaults work.Maybe someone can help me?
taskList VC file:
#IBAction func doneButton_Tapped(_ sender: Any) {
var newTask = taskList()
newTask.name = taskNameField.text!
newTask.dueDate = dueDatePicker.date
newTask.dateCreated = Date()
taskArr.append(newTask)
didCreateTask = true
self.navigationController?.popViewController(animated: true)
}
mainVC file:
struct taskList {
var name: String!
var dateCreated: Date!
var dueDate:Date!
}
private let listIdentifier = "listIdentifier"
var taskArr: [taskList] = []
let defauls = UserDefaults.standard
class ViewController: UIViewController {
#IBOutlet var tableView:UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Tasks List"
tableView.delegate = self
tableView.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}
#IBAction func newTaskButton_Tapped(_ sender: Any){
self.performSegue(withIdentifier: "newTaskSague", sender: nil)
}
}
extension ViewController: UITableViewDelegate{
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}
extension ViewController:UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {return taskArr.count}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: listIdentifier, for: indexPath) as! listCell
let row = indexPath.row
let formatter = DateFormatter()
cell.title?.text = taskArr[row].name
formatter.dateStyle = .medium
formatter.timeStyle = .short
cell.subTitle?.text = "Due: \(formatter.string(from: taskArr[row].dueDate))"
return cell
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete{
taskArr.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
}
With user defaults you can pretty much whatever you need but mind that is an internal database to small stuff as checking a boolean, an integer minimal data that you need as extra logic not as storage place, i you are planning to save a lot of entries of your Task model, you should consider to user CoreData.
What I suggest, is save an array of tasks in your UserDefaults (again if is not so much) and when you come from background, you need to check if your UserDefaults is empty, something like
override func viewDidLoad() {
super.viewDidLoad()
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(appMovedToForeground), name: Notification.Name.UIApplicationWillEnterForeground, object: nil)
}
func appMovedToForeground() {
print("come from background")
}
For objects array you will need to use archiver, you will need to add to that method of appMoveToForeground something like:
guard let dataTasks = UserDefaults.standard.object(forKey: "task") as? Data else { return nil }
if let tasks = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [Task.self], from: dataTasks){
if tasks.isNotEmpty() {
}
}
}
i still didnot get it how to implment this in my code .and im not trying to save big size of data just couple of them i dont need to use coreData
Related
Simple app but it's kicking my backside! I have a tableView with 4 notes, when user clicks on one, detailView Screen pops up allowing users to enter text. The challenge is to save each text that the user enters. I used UserDefaults as you'll see but I am not quite getting it right. I want to save each individual note. However, what keeps happening is that anytime I click on the row, and enter text, and save, that text gets saved into all 4 notes. I think my issue is coming from the didSelectRowAt() method but I am not sure. Please take a look and tell me what I need to do to access each individual note's textView in order to save them individually. My notes are contained in an array called notes, inside the main ViewController.swift.
here's my ViewController.swift
import UIKit
class ViewController: UITableViewController {
var notes = ["Note1", "Note2", "Note3", "Note4"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return notes.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = notes[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let vc = storyboard?.instantiateViewController(withIdentifier: "Detail") as? DetailViewController{
vc.selectedNote = notes[indexPath.row]
navigationController?.pushViewController(vc, animated: true)
}
}
}
and here's my detailViewController
import UIKit
class DetailViewController: UIViewController {
#IBOutlet var textView: UITextView!
var selectedNote: String?
var notesTwo = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let otherVC = ViewController()
notesTwo = otherVC.notes
let defaults = UserDefaults.standard
if let noteText = defaults.string(forKey: "noteText"){
textView.text = noteText
}
textView.font = UIFont(name: "Helvetica-Bold", size: 18)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let noteText = textView.text{
let defaults = UserDefaults.standard
defaults.set(noteText, forKey: "noteText")
}
}
}
If you use userdefault to save text, it will override previous data.
Option 1:
You should use core data / sqlite to save notes.
1)Create Entity(Notes) with two attribute createdDate and noteText
Save notes to from detail vc to core data with combination of created/modified date and notesText
Use fetchController to firstVc to update data
Option 2:
Create model with two instance variable and save model directly to user default
And and refresh firstVC ui in viewWillAppear
https://cocoacasts.com/ud-5-how-to-store-a-custom-object-in-user-defaults-in-swift
if you need to do this using user defaults, instead of notes you have to keep notes key that can use as user default key, then you can access them everywhere when you need.
here is the way of your code should be change:
class ViewController: UITableViewController {
var noteKeys = ["Note1", "Note2", "Note3", "Note4"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
//after your detail view controller dismiss time you have to reload your table view data again
self.tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return noteKeys.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let savedText: String = UserDefaults.standard.value(forKey: noteKeys[indexPath.item]) as? String ?? "empty"
cell.textLabel?.text = savedText
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let vc = storyboard?.instantiateViewController(withIdentifier: "Detail") as? DetailViewController{
vc.selectedNoteKey = noteKeys[indexPath.row]
navigationController?.pushViewController(vc, animated: true)
}
}
}
and inside DetailViewController code should be change like this:
class DetailViewController: UIViewController {
#IBOutlet var textView: UITextView!
var selectedNoteKey: String!
override func viewDidLoad() {
super.viewDidLoad()
textView.font = UIFont(name: "Helvetica-Bold", size: 18)
let defaults = UserDefaults.standard
if let noteText = defaults.string(forKey: self.selectedNoteKey){
textView.text = noteText
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let noteText = textView.text{
let defaults = UserDefaults.standard
defaults.set(noteText, forKey: self.selectedNoteKey)
defaults.synchronize()
}
}
}
The view shows duplicate rows for each record in CoreData which keep multiplying on each reload. The code is as under.
What happen is whenever I add record then I view record it shows me the record. Then I click back for the homepage after that when I click on view record I see the copy of same record. So now I have 2 same records. Can anyone please help me with and I think the problem is in table view so here is my table view controller code
import UIKit
import CoreData
var Rec = [Records]()
class TableViewController: UITableViewController {
var firstLoad = true
func nondel() -> [Records]
{
var nodellist = [Records]()
for note in Rec
{
if(note.del == nil)
{
nodellist.append(note)
}
}
return nodellist
}
override func viewDidLoad() {
super.viewDidLoad()
if(firstLoad)
{
firstLoad = false
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context:NSManagedObjectContext = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Records")
do{
let results: NSArray = try context.fetch(request) as NSArray
for result in results {
let note = result as! Records
Rec.append(note)
}
}
catch
{
print("Fetch Failed")
}
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell") as! TableViewCell
let thisrec: Records!
thisrec = nondel()[indexPath.row]
cell.idLB.text = thisrec.id
cell.nameLB.text = thisrec.name
cell.lastLB.text = thisrec.last
cell.genderLB.text = thisrec.gender
cell.ageLB.text = thisrec.age
cell.addressLB.text = thisrec.address
return cell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return nondel().count
}
override func viewDidAppear(_ animated: Bool) {
tableView.reloadData()
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
self.performSegue(withIdentifier: "editNote", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "editNote")
{
let indexPath = tableView.indexPathForSelectedRow!
let recDetail = segue.destination as? AddViewController
let selectedCell: Records!
selectedCell = nondel()[indexPath.row]
recDetail!.selectedCell = selectedCell
tableView.deselectRow(at: indexPath, animated: true)
}
}
}
Your code is unbelievable cumbersome.
First of all never declare a data source outside of any class.
Second of all never use a function to build an array as table view data source.
Third of all firstRun is pointless because viewDidLoad is called only once anyway.
Fourth of all rather than filtering the received records manually apply a predicate to the fetch request
Further it's highly recommended to name Core Data entities always in singular form (Record) and to use the specific generic fetch request of this entity.
class TableViewController: UITableViewController {
var records = [Record]()
override func viewDidLoad() {
super.viewDidLoad()
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request : NSFetchRequest<Record> = Record.fetchRequest()
request.predicate = NSPredicate(format: "del != nil")
do {
records = try context.fetch(request)
} catch { print("Fetch Failed", error) }
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell") as! TableViewCell
let thisrec = records[indexPath.row]
cell.idLB.text = thisrec.id
cell.nameLB.text = thisrec.name
cell.lastLB.text = thisrec.last
cell.genderLB.text = thisrec.gender
cell.ageLB.text = thisrec.age
cell.addressLB.text = thisrec.address
return cell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return records.count
}
...
I made a ToDo list app where I enter a task in one view controller and it saves the data in array of another view controller and then adds it to a table. My only problem is that when I close the app, all my new task data is gone. Can anyone help?
I tried using UserDefaults but it didn't work quite well or I just didn't use it right.
This is the code from the view controller where I type in the new task:
#IBAction func addTaskButton(_ sender: Any)
{
if (textField.text != "") {
Task.append(textField.text!)
let task = UserDefaults.standard.set(Task, forKey: "XX")
textField.text = ""
textLabel.text = "SAVED!"
timer = Timer.scheduledTimer(timeInterval: 1.6, target: self, selector: #selector(AddTaskViewController.Hide), userInfo: nil, repeats: true)
textLabel.isHidden = false
}
}
This is the code from the view controller where I try to save the Data and place it in a table
var Task = ["Pray", "Code", "Work-Out"]
var School = ["Email Collin College","Email PQC","Create file for all my doccumensts"]
var ShoppingList = ["KD9 Black","RoshRun Black","Nike Huarache Black","White Shirt","Black Shirt", "Black Work Out pnats", "White Socks"]
var Prayer = ["School","Family","Drive & Grace"]
var WorkOut = ["Legs","Caffs","Push Ups","Arms","Chest Press","Squats", "Back"]
class add_Task_TableViewController: UIViewController,UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var TaskTableView: UITableView!
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return (Task.count)
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "Cell")
cell.textLabel?.text = Task[indexPath.row]
return(cell)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
{
if editingStyle == UITableViewCellEditingStyle.delete
{
Task.remove(at: indexPath.row)
TaskTableView.reloadData()
}
}
override func viewDidAppear(_ animated: Bool) {
TaskTableView.reloadData()
}
You can use SQLITE as a database where you maintain your draft messages or values that can be used later when you open app again.
You can use userDefaults to save your todo List. But what you are missing is you are storing correctly but you are not retriving stored array from the userDefaults.
To solve this just change your viewDidAppear method as below code snippet.
override func viewDidAppear(_ animated: Bool) {
Task = UserDefaults.standard.stringArray(forKey: "XX") ?? [String]()
TaskTableView.reloadData()
}
My project is a reminder list and has only two view controllers(vc).
The first displays the tableview using Subtile style on the tableview cell. The second vc has two text labels, the date picker and save button.
My questions;
1) How do I send the time only to the label I have created in the tableview cell?
2) When adding the date picker to xcdatamodeld (core data), under Attribute what is the Type? I have tried Double, but that didn't work.
Greatly appreciate your support.
import UIKit
class AddEventViewController: UIViewController {
#IBOutlet weak var addReminderTextField: UITextField!
#IBOutlet weak var addInformationTextField: UITextField!
var datePicker: UIDatePicker!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.isTranslucent = false
}
override func viewDidLoad() {
super.viewDidLoad()
datePicker = UIDatePicker()
datePicker.center = view.center
view.addSubview(datePicker)
}
#IBAction func cancelButtonTapped(_ sender: Any) {
navigationController!.popViewController(animated: true)
}
#IBAction func saveButtonTapped(_ sender: Any) {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let task = Task(context: context)
task.title = addReminderTextField.text!
task.subtitle = addInformationTextField.text!
(UIApplication.shared.delegate as! AppDelegate).saveContext()
navigationController!.popViewController(animated: true)
}
}
And here is my tableview code...
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tasks.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath)
let task = tasks[indexPath.row]
cell.textLabel?.text = task.title!
cell.detailTextLabel?.text = task.subtitle
return cell
}
func getTasks() {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do {
tasks = try context.fetch(Task.fetchRequest())
}
catch {
print("Fetching Failed")
}
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
if editingStyle == .delete {
let task = tasks[indexPath.row]
context.delete(task)
(UIApplication.shared.delegate as! AppDelegate).saveContext()
do {
tasks = try context.fetch(Task.fetchRequest())
}
catch {
print("Fetching Failed")
}
}
tableView.reloadData()
}
}
I am currently experimenting with persistent data in swift, but I am having trouble saving this data and retrieving it back again. Basically I have two text fields, and when the user presses the submit button then the entry will be saved to a UITable, here the user will be able to move the entries in the table around or delete them if they so wish. My main problem is saving and loading this data.
Taskmanager.swift -- Here I have my basic types stored
import Foundation
import UIKit
var taskMgr: TaskManager = TaskManager()
struct task {
var name = "Name"
var year = "Year"
}
//setting data
let defaults = UserDefaults.standard
//defaults.synchronize()
//getting data
class TaskManager: NSObject {
var tasks = [task]()
func addTask(name: String, year: String){
tasks.append(task(name: name, year: year))
}
}
ThirdViewController.swift -- Here I have stored my table and its functions, I also have a rough sketch of save and load data functions.
import Foundation
import UIKit
class ThirdViewController:UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tableView: UITableView!
#IBAction func deleteT(_ sender: Any) {
if(tableView.isEditing == true){
tableView.setEditing(false, animated: true)
}else{
tableView.setEditing(true, animated: true)
}
}
func saveData() {
let data = NSMutableData()
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let path = paths[0]
let file = (path as NSString).appendingPathComponent("Persistent.plist")
//2
let archiver = NSKeyedArchiver(forWritingWith: data)
archiver.encode(G, forKey: "name")
archiver.endode(year, forKey: "year")
archiver.finishEncoding()
data.write(toFile: file, atomically: true)
}
func loadData() {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let path = paths[0]
let file = (path as NSString).appendingPathComponent("Persistent.plist")
// 1
if FileManager.default.fileExists(atPath: file) {
if let data = NSData(contentsOfFile: file) {
let unarchiver = NSKeyedUnarchiver(forReadingWith: data as Data)
name = unarchiver.decodeObjectForKey("name") as! [String]
year = unarchiver.decodeObjectForKey("year") as! [String]
unarchiver.finishDecoding()
}
}
}
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.reloadData()
loadData()
}
override func viewWillAppear(_ animated: Bool) {
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return taskMgr.tasks.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "TableView")
//Assign the contents of our var "items" to the textLabel of each cell
cell.textLabel!.text = taskMgr.tasks[indexPath.row].name
cell.detailTextLabel!.text = taskMgr.tasks[indexPath.row].year
//cell.editing = tableView(tableView, canMoveRowAtIndexPath: indexPath)
return cell
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath){
if (editingStyle == UITableViewCellEditingStyle.delete){
taskMgr.tasks.remove(at: indexPath.row)
tableView.reloadData()
}
}
}
FourthViewController.swift -- Here I have my textfields and buttons and how I am adding my entries to the table.
import Foundation
import UIKit
class FourthViewController: UIViewController, UITextFieldDelegate{
#IBOutlet var addT: UITextField!
#IBOutlet var addY: UITextField!
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 confTask(_ sender:UIButton){
if (addT.text == ""){
}else{
//add record
let name: String = addT.text!
let Year: String = addY.text!
//taskMgr.addTask(name:name)
taskMgr.addTask(name:name, year:Year)
}
//dismiss keyboard and reset fields
self.view.endEditing(true)
addT.text = nil
addY.text = nil
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool{
textField.resignFirstResponder()
return true
}
}
I have created some sample code using NSUserDefaults for persisting the tasks. It is a fairly simple example, as long as you are just experimenting, and only want to have less than a 100 elements, it should be fine. Using the code below you should be able to display, remove and save tasks.
However, in the future, i would highly recommend you to read more into Core Data. There are many great tutorials out there, like this one.
I have created a Task object model, and TaskManager for reading, saving and removing tasks.
import Foundation
// Task Data Model
class Task: NSObject, NSCoding {
let name: String
let year: String
required init(name: String, year: String) {
self.name = name
self.year = year
}
required init(coder decoder: NSCoder) {
self.name = decoder.decodeObject(forKey: "name") as? String ?? ""
self.year = decoder.decodeObject(forKey: "year") as? String ?? ""
}
func encode(with coder: NSCoder) {
coder.encode(name, forKey: "name")
coder.encode(year, forKey: "year")
}
}
class TaskManager {
/// UserDefaults instance
private let defaults = UserDefaults.standard
/// Singleton instance, class **should** be accessed by this property
static let shared = TaskManager()
/// Indetifier of tasks container in `defaults`
private let kTasksIdentifier = "tasks"
/// Add a new task to your container and syncronize it into `defaults`
///
/// - Parameters:
/// - name: Name of the task
/// - year: Year of the task
func save(taskName name: String, year: String) {
let task = Task(name: name, year: year)
// Check if there is already saved tasks
guard let data = defaults.value(forKey: kTasksIdentifier) as? Data, var tasks = NSKeyedUnarchiver.unarchiveObject(with: data) as? [Task] else {
// If not, save it as the first one
syncronizeTasks(tasks: [task])
return
}
tasks.append(task)
syncronizeTasks(tasks: tasks)
}
/// Remove a task at an index
///
/// - Parameters:
/// - index: The index of the removeable task
func remove(at index: Int) {
guard let data = defaults.value(forKey: kTasksIdentifier) as? Data, var tasks = NSKeyedUnarchiver.unarchiveObject(with: data) as? [Task] else {
fatalError("Unable to retrive tasks from defaults")
}
tasks.remove(at: index)
syncronizeTasks(tasks: tasks)
}
/// Read all tasks elements
/// If there are tasks in memory, it returns the one from memory
/// Otherwise reads it from `UserDefaults`
///
/// - Returns: all tasks elements available, return empty array if no elements found
func readAllTasks() -> [Task] {
let data = UserDefaults.standard.value(forKey: kTasksIdentifier)
let allTasks = NSKeyedUnarchiver.unarchiveObject(with: data as! Data)
return allTasks as? [Task] ?? [Task]()
}
private func syncronizeTasks(tasks: [Task]) {
let data = NSKeyedArchiver.archivedData(withRootObject: tasks)
defaults.set(data, forKey: kTasksIdentifier)
defaults.synchronize()
}
}
I have modified your already existing ThirdViewController a bit.
import UIKit
import Foundation
class ThirdViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tableView: UITableView!
/// Your tasks being updated in this collection every time `refreshTasks()` is being called
private var tasks = [Task]()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.refreshTasks()
self.tableView.reloadData()
}
func refreshTasks() {
self.tasks = TaskManager.shared.readAllTasks()
}
#IBAction func deleteT(_ sender: Any) {
if(tableView.isEditing == true) {
tableView.setEditing(false, animated: true)
} else {
tableView.setEditing(true, animated: true)
}
}
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return tasks.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "TableView")
//Assign the contents of our var "items" to the textLabel of each cell
cell.textLabel!.text = tasks[indexPath.row].name
cell.detailTextLabel!.text = tasks[indexPath.row].year
//cell.editing = tableView(tableView, canMoveRowAtIndexPath: indexPath)
return cell
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath){
if (editingStyle == UITableViewCellEditingStyle.delete) {
self.tableView.beginUpdates()
TaskManager.shared.remove(at: indexPath.row)
refreshTasks()
self.tableView.deleteRows(at: [indexPath], with: .fade)
self.tableView.endUpdates()
}
}
}
And, just in case, edited your FourthViewController too
import Foundation
import UIKit
class FourthViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var addT: UITextField!
#IBOutlet var addY: UITextField!
/// User has pressed `Submit` button
///
/// - Parameter sender: the pressed button
#IBAction func confTask(_ sender: UIButton) {
// Check if textfields are containing text
guard let nameText = addT.text, let yearText = addY.text, !nameText.isEmpty, !yearText.isEmpty else {
print("at least one of the textFields is not filled")
return
}
// Save the tasks
TaskManager.shared.save(taskName: nameText, year: yearText)
//dismiss keyboard and reset fields
self.view.endEditing(true)
addT.text = nil
addY.text = nil
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool{
textField.resignFirstResponder()
return true
}
}