How to get the current date using Date class in Swift - ios

I'm making my app to be able to save the user tasks, now I would like to add the date to the subtitle in the tableview. now the problem is I don't get how can I get the current date every time the user creates a task, could be cool for some tips and sorry if I break any stackOverFlow rules :)
Here's my code to the VC of my tableview:
import UIKit
import Foundation
import SwipeCellKit
import CoreData
//MARK: - Protocol to transfer the task Label to main VC:
protocol TaskDelegate {
func updateTaskName(name:String)
}
//MARK: - Tasks View Controller:
class TasksViewController: UITableViewController, SwipeTableViewCellDelegate {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var tasksArray = [Task]()
var delegate: TaskDelegate?
var taskName = ""
override func viewDidLoad(){
super.viewDidLoad()
loadTasks()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.prefersLargeTitles = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.navigationBar.prefersLargeTitles = false
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return tasksArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell") as! SwipeTableViewCell
cell.delegate = self
cell.textLabel?.text = tasksArray[indexPath.row].title
cell.imageView?.image = UIImage(named: "icon-unchecked-checkbox.png")
cell.detailTextLabel?.text = ""
return cell
}
// MARK: - Table view delegate methods:
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
guard orientation == .right else { return nil }
let deleteAction = SwipeAction(style: .destructive , title: .none) { action, indexPath in
// handle action by updating model with deletion
self.context.delete(self.tasksArray[indexPath.row])
self.tasksArray.remove(at: indexPath.row)
self.delegate?.updateTaskName(name: "")
self.saveTasks()
}
let infoAction = SwipeAction(style: .default, title: .none) { action, indexPath in return }
deleteAction.transitionDelegate = ScaleTransition.default
// deleteAction.transitionDelegate = ScaleTransition.init(duration: 0.50, initialScale: 0.50, threshold: 0.50)
infoAction.transitionDelegate = ScaleTransition.default
// customize the action appearance
deleteAction.image = UIImage(named: "icon-trash")
infoAction.image = UIImage(named: "icon-more")
return [deleteAction, infoAction]
}
// method to customize the behavior of the swipe actions(the delete action):
func tableView(_ tableView: UITableView, editActionsOptionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> SwipeOptions {
var options = SwipeOptions()
options.expansionStyle = .destructive
options.transitionStyle = .drag
options.buttonSpacing = 10
options.expansionDelegate = ScaleAndAlphaExpansion.init(duration: 0.15, scale: 0.5, interButtonDelay: 0.30)
return options
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if tableView.cellForRow(at: indexPath)?.imageView?.image == UIImage(named: "icon-checked-checkbox.png") {
let imageBox = UIImage(named: "icon-unchecked-checkbox.png")
tableView.cellForRow(at: indexPath)?.imageView?.image = imageBox
} else {
let imageBox = UIImage(named: "icon-checked-checkbox.png")
tableView.cellForRow(at: indexPath)?.imageView?.image = imageBox
}
}
// MARK: - Class Methods:
//Adding task function:
#IBAction func addPressedButton(_ sender: UIBarButtonItem) {
var textField = UITextField()
let alert = UIAlertController(title: "New Task", message: "Please insert a new task.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
alert.addTextField(configurationHandler: { alertTextField in
alertTextField.placeholder = "Please insert your task"
textField = alertTextField
})
alert.addAction(UIAlertAction(title: "OK", style: .destructive, handler: { action in
//We Add the task into our array of Task objects once we reach into here:
let newTask = Task(context: self.context)
newTask.title = textField.text
self.taskName = newTask.title!
self.delegate?.updateTaskName(name: self.taskName)
self.tasksArray.append(newTask)
self.saveTasks()
self.tableView.reloadData()
}))
self.present(alert, animated: true)
}
func getDate() -> String{
let dateFormatter : DateFormatter = DateFormatter()
// dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.dateFormat = "yyyy-MMM-dd HH:mm:ss"
let date = Date()
let dateString = dateFormatter.string(from: date)
let interval = date.timeIntervalSince1970
return dateString
}
}
here's the picture of my tableview - https://imgur.com/iFcr1iN

You can get current date using Date class
func getDate(date: Date) -> String{
let dateFormatter : DateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MMM-dd HH:mm:ss"
let dateString = dateFormatter.string(from: date)
return dateString
}
how to use subtitle
cell.detailTextLabel?.text = getDate(date:Date())

Related

How can I fix the error that says no value inputs to core data?

I would like to save the values "title: String" and "done: Boolean" by following sentences. Title is written in textfield in Alert, and done is set as false as default. but there are errors saying no value is input to core data.
How can I fix this?
import UIKit
import CoreData
class TodoListViewController: UITableViewController {
var itemArray = [Item]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - TableViewDataSource Methods
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ToDoItemCell", for: indexPath)
let item = Item(context: context)
cell.textLabel?.text = item.title
cell.accessoryType = item.done ? .checkmark : .none
return cell
}
// MARK: - TableView Delegate Methods
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
itemArray[indexPath.row].done = !itemArray[indexPath.row].done
tableView.deselectRow(at: indexPath, animated: true)
tableView.reloadData()
self.saveItems()
}
// MARK: - Add New Items
#IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "Add New Todoey Item", message: "", preferredStyle: .alert)
var textField = UITextField()
let newItem = Item(context: self.context)
alert.addTextField { (alertTextField) in
alertTextField.placeholder = "Create new item"
textField = alertTextField
}
let action = UIAlertAction(title: "Add Item", style: .default) { (action) in
print(textField.text ?? "no data")
newItem.title = alert.textFields?.first?.text ?? ""
newItem.done = false
self.itemArray.append(newItem)
print(self.itemArray)
print(newItem)
self.saveItems()
self.tableView.reloadData()
}
alert.addAction(action)
present(alert, animated: true, completion: nil)
}
func saveItems(){
do {
print("\(context)")
try context.save()
}catch {
print("error, \(error)")
}
}
Error message is as follows:
error, Error Domain=NSCocoaErrorDomain Code=1570 "title is a required value." UserInfo={NSValidationErrorObject=<Todoey.Item: 0x600000424a00> (entity: Item; id: 0x60000277c4c0 x-coredata:///Item/tA47CD9C0-9813-49C7-9594-91AFFCFE511F3; data: {
done = 0;
title = nil;
}), NSLocalizedDescription=title is a required value., NSValidationErrorKey=title, NSValidationErrorValue=null}
It is the first time to ask a question here. If there is more detail required, please let me know.
I write in the textfield, but there is no text in tableView. but when I print , there is a right input.
how app works
code of appdelegate
delegate properties in viewcontroller

Edit operation is not working in Core Data

I'm working on core data crud operation.I've Person object and when user click on add (+) button user can add the person name and person name will show in tableview. When user click on any tableView cell it shows the alert and current tap cell person show in alert text field and user can edit the name of person but my logic is not working fine and user is not editing.I've one more problem like when i run the app the pervious users record not showing but it will showing after I will enter the new user and fetch all the pervious users see the code and guide me thanks in advance.
ViewController Class:
#IBOutlet weak var tableView: UITableView!
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var items : [Person] = [] {
didSet{
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
tableView.register(UINib(nibName: String(describing: StundentCell.self), bundle: .main), forCellReuseIdentifier: String(describing: StundentCell.self))
}
#IBAction func addPerson(_ sender: UIBarButtonItem) {
showAlert()
}
private func showAlert(_ title:String = "Add new Item", message: String = "what is your name"){
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
alertController.addTextField()
let subbmitBtn = UIAlertAction(title: "Add Person", style: .default) { (action) in
let textField = alertController.textFields![0]
let newPerson = Person(context:self.context)
newPerson.name = textField.text
newPerson.age = 20
newPerson.gender = "Male"
do {
try self.context.save()
}
catch{
}
self.fetchPerople()
}
alertController.addAction(subbmitBtn)
self.present(alertController, animated: true, completion: nil)
}
func fetchPerople(){
do{
self.items = try context.fetch(Person.fetchRequest())
}
catch{
}
}
}
extension ViewController: UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
self.configurePersonCell(tableView, cellForRowAt: indexPath)
}
func configurePersonCell(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: StundentCell.self)) as? StundentCell else {return UITableViewCell()}
cell.studentData = items[indexPath.row]
cell.delete.tag = indexPath.row
cell.delete.addTarget(self, action: #selector(deleteRecord(sender:)), for: .touchUpInside)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var person = items[indexPath.row].name
let alertController = UIAlertController(title: "Edit Person", message: "Edit name", preferredStyle: .alert)
alertController.addTextField()
let alertField = alertController.textFields![0]
alertField.text = person
let saveBtn = UIAlertAction(title: "Save", style: .default) { (action) in
let getName = alertController.textFields![0]
person = getName.text
do{
try self.context.save()
}
catch{
}
self.fetchPerople()
}
alertController.addAction(saveBtn)
self.present(alertController, animated: true, completion: nil)
}
func gotoPersonDetails(personData:Person){
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
#objc func deleteRecord(sender: UIButton){
if items.count > 0{
let personRemove = self.items[sender.tag]
self.context.delete(personRemove)
do {
try self.context.save()
}
catch{
}
self.fetchPerople()
}
}
#IBOutlet weak var tableView: UITableView!
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var items : [Person] = [] {
didSet{
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
tableView.register(UINib(nibName: String(describing: StundentCell.self), bundle: .main), forCellReuseIdentifier: String(describing: StundentCell.self))
}
#IBAction func addPerson(_ sender: UIBarButtonItem) {
showAlert()
}
private func showAlert(_ title:String = "Add new Item", message: String = "what is your name"){
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
alertController.addTextField()
let subbmitBtn = UIAlertAction(title: "Add Person", style: .default) { (action) in
let textField = alertController.textFields![0]
let newPerson = Person(context:self.context)
newPerson.name = textField.text
newPerson.age = 20
newPerson.gender = "Male"
do {
try self.context.save()
}
catch{
}
self.fetchPerople()
}
alertController.addAction(subbmitBtn)
self.present(alertController, animated: true, completion: nil)
}
func fetchPerople(){
do{
self.items = try context.fetch(Person.fetchRequest())
}
catch{
}
}
}
extension ViewController: UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
self.configurePersonCell(tableView, cellForRowAt: indexPath)
}
func configurePersonCell(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: StundentCell.self)) as? StundentCell else {return UITableViewCell()}
cell.studentData = items[indexPath.row]
cell.delete.tag = indexPath.row
cell.delete.addTarget(self, action: #selector(deleteRecord(sender:)), for: .touchUpInside)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var person = items[indexPath.row].name
let alertController = UIAlertController(title: "Edit Person", message: "Edit name", preferredStyle: .alert)
alertController.addTextField()
let alertField = alertController.textFields![0]
alertField.text = person
let saveBtn = UIAlertAction(title: "Save", style: .default) { (action) in
//get the person name in alert text field
let getName = alertController.textFields![0]
//edit the name of the person object
person = getName.text
do{
try self.context.save()
}
catch{
}
self.fetchPerople()
}
alertController.addAction(saveBtn)
self.present(alertController, animated: true, completion: nil)
}
func gotoPersonDetails(personData:Person){
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
#objc func deleteRecord(sender: UIButton){
/* fro api calling or firebase for deleting the rows in tableview
if items.count > 0 {
items.remove(at:sender.tag)
}
*/
if items.count > 0{
let personRemove = self.items[sender.tag]
//remove the person
self.context.delete(personRemove)
//save the data
do {
try self.context.save()
}
catch{
}
//refetch the data
self.fetchPerople()
}
}
You are modifying the name string but you don't update the record.
Get the whole person
let person = items[indexPath.row] // can be a constant because it's reference type
assign the name to the text field
alertField.text = person.name
and assign the edited name back
let nameField = alertController.textFields![0]
person.name = nameField.text
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let person = items[indexPath.row]
let alertController = UIAlertController(title: "Edit Person", message: "Edit name", preferredStyle: .alert)
alertController.addTextField()
let alertField = alertController.textFields![0]
alertField.text = person.name
let saveBtn = UIAlertAction(title: "Save", style: .default) { (action) in
let nameField = alertController.textFields![0]
person.name = nameField.text
do{
try self.context.save()
}
catch{
}
self.fetchPerople()
}
alertController.addAction(saveBtn)
self.present(alertController, animated: true, completion: nil)
}

My TableView only lists the last item in my itemArray?

I have four items in my itemArray, but my TableView only lists my last appended item, and it lists it first. However, I can check and uncheck the three rows below the first row that actually has a text.
import UIKit
class ToDoListViewController: UITableViewController {
var itemArray = [Item]()
let defaults = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
let newItem = Item()
newItem.title = "Find Mike"
itemArray.append(newItem)
let newItem2 = Item()
newItem.title = "Buy Eggos"
itemArray.append(newItem2)
let newItem3 = Item()
newItem.title = "Destroy Demongorgon"
itemArray.append(newItem3)
let newItem4 = Item()
newItem.title = "RockOn!"
itemArray.append(newItem4)
// if let items = defaults.array(forKey: "ToDoListArray") as? [String] {
// itemArray = items
// }
}
//MARK: - TableView Datasource Methods
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ToDoItemCell", for: indexPath)
let item = itemArray[indexPath.row]
cell.textLabel?.text = item.title
cell.accessoryType = item.done ? .checkmark : .none
return cell
}
//MARK: - TableView Delegate Methods
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//print(itemArray[indexPath.row])
itemArray[indexPath.row].done = !itemArray[indexPath.row].done
tableView.reloadData()
tableView.deselectRow(at: indexPath, animated: true)
}
//MARK: - Add New Items
#IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
var textField = UITextField()
let alert = UIAlertController(title: "Add New Todoey Item", message: "", preferredStyle: .alert)
let action = UIAlertAction(title: "Add Item", style: .default) { (action) in
//what will happen once the user clicks the add item
let newItem = Item()
newItem.title = textField.text!
self.itemArray.append(newItem)
self.defaults.set(self.itemArray, forKey: "ToDoListArray")
self.tableView.reloadData()
}
alert.addTextField { (alertTextField) in
alertTextField.placeholder = "Create new item"
textField = alertTextField
}
alert.addAction(action)
present(alert, animated: true, completion: nil)
}
}
StackOverflow say I need more of a description... I think this says it all... This is for a Udemy iOS series...
You have used same instance for set item name. Change your viewDidLoad method.
override func viewDidLoad() {
super.viewDidLoad()
let newItem = Item()
newItem.title = "Find Mike"
itemArray.append(newItem)
let newItem2 = Item()
newItem2.title = "Buy Eggos"
itemArray.append(newItem2)
let newItem3 = Item()
newItem3.title = "Destroy Demongorgon"
itemArray.append(newItem3)
let newItem4 = Item()
newItem4.title = "RockOn!"
itemArray.append(newItem4)
// if let items = defaults.array(forKey: "ToDoListArray") as? [String] {
// itemArray = items
// }
}
check this and it's working, Your code after some slight edits:
import UIKit
class Item {
var title: String
var done: Bool
init(itemTitle: String, itemStatus: Bool) {
title = itemTitle
done = itemStatus
}
}
class ToDoListViewController: UITableViewController {
var itemArray = [Item]()
let defaults = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
addItemsToArray()
// if let items = defaults.array(forKey: "ToDoListArray") as? [String] {
// itemArray = items
// }
}
//MARK: - add Items
func addItemsToArray(){
let newItem = Item(itemTitle: "Find Mike", itemStatus: false)
itemArray.append(newItem)
let newItem2 = Item(itemTitle: "Buy Eggos", itemStatus: false)
itemArray.append(newItem2)
let newItem3 = Item(itemTitle: "Destroy Demongorgon", itemStatus: false)
itemArray.append(newItem3)
let newItem4 = Item(itemTitle: "RockOn!", itemStatus: false)
itemArray.append(newItem4)
}
//MARK: - TableView Datasource Methods
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ToDoItemCell", for: indexPath)
cell.textLabel?.text = itemArray[indexPath.row].title
cell.accessoryType = itemArray[indexPath.row].done ? .checkmark : .none
return cell
}
//MARK: - TableView Delegate Methods
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//print(itemArray[indexPath.row])
itemArray[indexPath.row].done = !itemArray[indexPath.row].done
tableView.reloadData()
tableView.deselectRow(at: indexPath, animated: true)
}
//MARK: - Add New Items
#IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
var textField = UITextField()
let alert = UIAlertController(title: "Add New Todoey Item", message: "", preferredStyle: .alert)
let action = UIAlertAction(title: "Add Item", style: .default) { (action) in
//what will happen once the user clicks the add item
let newItem = Item(itemTitle: textField.text!, itemStatus: false)
self.itemArray.append(newItem)
self.defaults.set(self.itemArray, forKey: "ToDoListArray")
self.tableView.reloadData()
}
alert.addTextField { (alertTextField) in
alertTextField.placeholder = "Create new item"
textField = alertTextField
}
alert.addAction(action)
present(alert, animated: true, completion: nil)
}
}
The problem in your implementation is that you are using the same instance you are appending newItem instead of newItem2 and newItem3
I would strongly advise using the below approach I will provide, it is safe and be customize easily
struct Item {
var titleName: String?
var description: String?
init(titleName: String, description: String) {
self.titleName = titleName
self.description = description
}
}
enum ItemOptions: Int, CaseIterable {
case Find
case Local
case Search
var title: String {
switch self {
case .Find: return "Find"
case .Local: return "Local"
case .Search: return "Search"
}
}
var desciprion: String {
switch self {
case .Find: return "Find Desc"
case .Local: return "Local Desc"
case .Search: return "Search Desc"
}
}
}
class ToDoListViewController: UITableViewController {
var itemArray = [Item]()
let defaults = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
for item in ItemOptions.allCases {
itemArray.append(Item(titleName: item.title, description: item.desciprion))
}
}
}
You can update the item Struct and add multiple values and only you change the enum either add maybe a new image, price.

Value of type 'Item' has no member 'parentCategory'

I have 2 entities
I'm using XCode 10 right now, I am not sure if I did something wrong or XCode bug.
I added 1 line into these lines
let newItem = Item(context: self.context)
newItem.title = textField.text!
newItem.done = false
newItem.parentCategory = self.selectedCategory <--------- ADD HERE
self.itemArray.append(newItem)
self.saveItems()
Any hints for me on why this is happening ?
TodoListVC
//
// TodoListVC
// ListHue
// Copyright © 2018 LR Web Design. All rights reserved.
//
import UIKit
import CoreData
class TodoListVC: UITableViewController {
var itemArray = [Item]()
var selectedCategory : Category? {
didSet {
loadItems()
}
}
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
// ---------------------------------------------------------------------------------------------------------
//MARK - viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
print(FileManager.default.urls(for: .documentDirectory, in: .userDomainMask))
}
// ---------------------------------------------------------------------------------------------------------
//MARK - Datasource
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "listItemCell", for: indexPath)
let item = itemArray[indexPath.row]
cell.textLabel?.text = item.title
cell.accessoryType = item.done == true ? .checkmark : .none
return cell
}
// ---------------------------------------------------------------------------------------------------------
//MARK - Delegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
context.delete(itemArray[indexPath.row])
itemArray.remove(at: indexPath.row)
itemArray[indexPath.row].done = !itemArray[indexPath.row].done
self.saveItems()
tableView.deselectRow(at: indexPath, animated: true)
}
// ---------------------------------------------------------------------------------------------------------
//MARK - Add new item
#IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
var textField = UITextField()
let alert = UIAlertController(title: "Add New Item", message: "", preferredStyle: .alert)
//action
let action = UIAlertAction(title: "Add Item", style: .default) { (action) in
let newItem = Item(context: self.context)
newItem.title = textField.text!
newItem.done = false
newItem.parentCategory = self.selectedCategory
self.itemArray.append(newItem)
self.saveItems()
}
alert.addTextField { (alertTextField) in
alertTextField.placeholder = "Create new item"
textField = alertTextField
}
alert.addAction(action)
present(alert, animated: true, completion: nil)
}
// ---------------------------------------------------------------------------------------------------------
//MARK - Model Manipulation Methods
func saveItems() {
do {
try context.save()
} catch {
print("Error saving context, \(error)")
}
self.tableView.reloadData()
}
func loadItems(with request: NSFetchRequest<Item> = Item.fetchRequest()) {
let predicate = NSPredicate(format: "parentCategory.name MATCHES %#", selectedCategory?.name!)
request.predicate = predicate
do {
itemArray = try context.fetch(request)
} catch {
print("Error fetching data from the context, \(error)")
}
self.tableView.reloadData()
}
}
//MARK: - Search bar methods
extension TodoListVC : UISearchBarDelegate {
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
let request : NSFetchRequest<Item> = Item.fetchRequest()
request.predicate = NSPredicate(format: "title CONTAINS[cd] %#", searchBar.text!)
request.sortDescriptors = [NSSortDescriptor(key: "title", ascending: true)]
loadItems(with: request)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text?.count == 0 {
loadItems()
DispatchQueue.main.async {
searchBar.resignFirstResponder()
}
}
}
}
CategoryVC
//
// CategoryVC.swift
// ListHue
// Copyright © 2018 LR Web Design. All rights reserved.
//
import UIKit
import CoreData
class CategoryVC: UITableViewController {
var categories = [Category]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
loadCategories()
}
// ---------------------------------------------------------------------------------------------------------
//MARK - Table View Datasource
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return categories.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryCell", for: indexPath)
let category = categories[indexPath.row]
cell.textLabel?.text = category.name
return cell
}
// ---------------------------------------------------------------------------------------------------------
//MARK - Table View Delegate Methods
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
performSegue(withIdentifier: "goToItems", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.destination as! TodoListVC
//get the category of the selected cell
if let indexPath = tableView.indexPathForSelectedRow {
//set the property
destinationVC.selectedCategory = categories[indexPath.row]
}
}
// ---------------------------------------------------------------------------------------------------------
//MARK - Data Manipulation Methods
#IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
print("click")
var textField = UITextField()
let alert = UIAlertController(title: "Add New Category", message: "", preferredStyle: .alert)
//action
let action = UIAlertAction(title: "Add Category", style: .default) { (action) in
let newCategory = Category(context: self.context)
newCategory.name = textField.text!
self.categories.append(newCategory)
self.saveCategories()
}
alert.addTextField { (alertTextField) in
alertTextField.placeholder = "Create new item"
textField = alertTextField
}
alert.addAction(action)
present(alert, animated: true, completion: nil)
}
// ---------------------------------------------------------------------------------------------------------
//MARK - Add New Categories
func saveCategories() {
do {
try context.save()
} catch {
print("Error saving context, \(error)")
}
self.tableView.reloadData()
}
func loadCategories(with request: NSFetchRequest<Category> = Category.fetchRequest()) {
do {
categories = try context.fetch(request)
} catch {
print("Error fetching data from the context, \(error)")
}
self.tableView.reloadData()
}
}
I got the diagram backward, thanks to #Larme, and #Ladislav helped me to know that.

Firebase Data not showing in TableView

So basically I want to get the data from Firebase and put it in the tableView and then when a cell is deleted I want to remove the data from firebase and the table view...but with my code the data is NOT even showing up in the TableView and i really don't know what's wrong...?
Here's my Database structure if it helps:
Structure
I put the data in Courses then a childByAutoId which contains CourseName,AmountOfHoles and AddedDate then get it back in a snapshot, store the snapshot in an array called courses and then get the variables for the cell in cellForRowAtIndexPath but somehow the cell is not showing on the tableView...then I would delete the cell and data in commitEditingStyle but it doesn't even get to that because the cells don't show up...
I'm new to StackOverflow, so please excuse me if something seems stupid or wrong ...dont bother to tell me tho..
class CoursesViewController: UITableViewController {
var ref = FIRDatabaseReference.init()
override func viewDidLoad() {
ref = FIRDatabase.database().reference()
tableView.allowsMultipleSelectionDuringEditing = false
//let a = ref.childByAutoId()
//a.setValue("hi")
}
var courses: [FIRDataSnapshot]! = []
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let CoursesRef = ref.child("Courses")
CoursesRef.observeEventType(.ChildAdded, withBlock: { snapshpt in
self.courses.append(snapshpt)
})
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.courses.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->
UITableViewCell {
let cell: UITableViewCell! = self.tableView .dequeueReusableCellWithIdentifier("ItemCell", forIndexPath: indexPath)
let courseSnap: FIRDataSnapshot! = self.courses[indexPath.row]
let course = courseSnap.value
let coursename = course?.objectForKey("CourseName") as! String
let amountofholes = course?.objectForKey("AmountOfHoles") as! String
let addeddate = course?.objectForKey("AddedDate") as! String
cell.textLabel?.text = coursename + " " + amountofholes + " Holes"
cell.detailTextLabel?.text = addeddate
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 {
// Find the snapshot and remove the value
let courseitem = courses[indexPath.row]
courseitem.ref.removeValue()
}
}
#IBAction func addButtonDidTouch(sender: AnyObject) {
// Alert View for input
let alert = UIAlertController(title: "Course Item",message: "Add Course",preferredStyle: .Alert)
let saveAction = UIAlertAction(title: "Save", style: .Default) { (action: UIAlertAction) -> Void in
//Get Date String
let date = NSDate()
print(date)
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy 'at' HH:mm"
let dateString = dateFormatter.stringFromDate(date)
print(dateString)
//
let courseField = alert.textFields![0]
let holesField = alert.textFields![1]
let Courses = self.ref.child("Courses").childByAutoId()
let course = ["AddedDate": dateString as AnyObject,
"CourseName": courseField.text as! AnyObject,
"AmountOfHoles": holesField.text as! AnyObject]
Courses.setValue(course)
}
//Cancel
let cancelAction = UIAlertAction(title: "Cancel", style: .Default) { (action: UIAlertAction) -> Void in
}
//TextField placeholder in alert
alert.addTextFieldWithConfigurationHandler {
(courseField: UITextField!) -> Void in
courseField.placeholder = "Course Name"
}
alert.addTextFieldWithConfigurationHandler {
(holesField: UITextField!) -> Void in
holesField.placeholder = "Holes (6/9/18)"
}
//Add alert
alert.addAction(saveAction)
alert.addAction(cancelAction)
presentViewController(alert, animated: true, completion: nil)
}
}
Man you have to insert your code when a snapshot is found out !
I think you can go like this :
CoursesRef.observeEventType(.ChildAdded, withBlock: { snapshot in
self.courses.append(snapshot)
self.yourTable.insertRowsAtIndexPaths([NSIndexPath(forRow: self.courses.count-1, inSection: 0)], withRowAnimation: .Bottom)
})
check with this code
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(self.courses.count > 0){
tablecount = self.courses.count
} else {
tablecount = 0
self.table.reloaddata()
}
return tablecount
}

Resources