Save user input data of UITableView
There is an option in my app to add new excercises (via user input), i've managed to set the alert and add feature, but I can't save the data added and let it be persistent after closure and that.
//
// ExcerciseListViewController.swift
// OneRepMax
//
// Created by Mauro Garcia on 17/01/2019.
// Copyright © 2019 Mauro Garcia. All rights reserved.
//
import Foundation
import UIKit
import CoreData
class ExcerciseListViewController: UIViewController, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
title = "Excercises"
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
// This view controller itself will provide the delegate methods and row data for the table view.
tableView.delegate = self
tableView.dataSource = self
}
@IBOutlet weak var tableView: UITableView!
// Add a new excercise
@IBAction func addExcercise(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "New Excercise", message: "Add a new excercise", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
guard let textField = alert.textFields?.first,
let nameToSave = textField.text
else {
return
}
print(nameToSave)
self.excercises.append(nameToSave)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
alert.addTextField()
alert.addAction(saveAction)
alert.addAction(cancelAction)
present(alert, animated: true)
}
var excercises: [String] =
}
// MARK: - UITableViewDataSource
extension ExcerciseListViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
print(excercises.count)
return excercises.count
}
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
let cell =
tableView.dequeueReusableCell(withIdentifier: "Cell",
for: indexPath)
cell.textLabel?.text = excercises[indexPath.row]
return cell
}
// What happens when user touch an excercise
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let excerciseChosen = "(excercises[indexPath.row])"
goBackToOneButtonTapped((Any).self)
excUserChose = excerciseChosen
print(excUserChose)
print("You tapped cell number (indexPath.row).")
print(excerciseChosen)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "changeText"), object: nil)
}
func goBackToOneButtonTapped(_ sender: Any) {
performSegue(withIdentifier: "unwindToViewController", sender: self)
}
}
// TODO: save user input
In my AppDelegate.swift
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded the store for the
application to it. This property is optional since there are legitimate
error conditions that could cause the creation of the store to fail.
*/
let container = NSPersistentContainer(name: "OneRepMax")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error (error), (error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error (nserror), (nserror.userInfo)")
}
}
}
I want to -when the user press "Save"- to save the data to be accesible after.
I've tried to implement CoreData but I have failed trying. Don't know what I'm doing wrong.
EDIT:
Code for adding and saving input
var excercisess: [NSManagedObject] =
@IBAction func addExcercise(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "New Excercise", message: "Add a new excercise", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
guard let textField = alert.textFields?.first,
let nameToSave = textField.text
else {
return
}
self.save(name: nameToSave)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
alert.addTextField()
alert.addAction(saveAction)
alert.addAction(cancelAction)
present(alert, animated: true)
}
func save(name: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
/*1.
Before you can save or retrieve anything from your Core Data store, you first need to get your hands on an NSManagedObjectContext. You can consider a managed object context as an in-memory “scratchpad” for working with managed objects.
Think of saving a new managed object to Core Data as a two-step process: first, you insert a new managed object into a managed object context; then, after you’re happy with your shiny new managed object, you “commit” the changes in your managed object context to save it to disk.
Xcode has already generated a managed object context as part of the new project’s template. Remember, this only happens if you check the Use Core Data checkbox at the beginning. This default managed object context lives as a property of the NSPersistentContainer in the application delegate. To access it, you first get a reference to the app delegate.
*/
let managedContext = appDelegate.persistentContainer.viewContext
/*
An NSEntityDescription object is associated with a specific class instance
Class
NSEntityDescription
A description of an entity in Core Data.
Retrieving an Entity with a Given Name here person
*/
let entity = NSEntityDescription.entity(forEntityName: "Excercise", in: managedContext)!
/*
Initializes a managed object and inserts it into the specified managed object context.
init(entity: NSEntityDescription,
insertInto context: NSManagedObjectContext?)
*/
let excercises = NSManagedObject(entity: entity, insertInto: managedContext)
//we can simply create person object this way also.
// let excercise = Excercise(context: managedContext)
/*
With an NSManagedObject in hand, you set the name attribute using key-value coding. You must spell the KVC key (name in this case) exactly as it appears in your Data Model
*/
excercises.setValue(name, forKeyPath: "name")
/*
You commit your changes to person and save to disk by calling save on the managed object context. Note save can throw an error, which is why you call it using the try keyword within a do-catch block. Finally, insert the new managed object into the people array so it shows up when the table view reloads.
*/
do {
try managedContext.save()
excercisess.append(excercises)
tableView.reloadData()
print("SAVED")
} catch let error as NSError {
print("Could not save. (error), (error.userInfo)")
}
}
And the code for fetching:
func fetchAllExcercises(){
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
/*Before you can do anything with Core Data, you need a managed object context. */
let managedContext = appDelegate.persistentContainer.viewContext
/*As the name suggests, NSFetchRequest is the class responsible for fetching from Core Data.
Initializing a fetch request with init(entityName:), fetches all objects of a particular entity. This is what you do here to fetch all Person entities.
*/
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Excercise")
/*You hand the fetch request over to the managed object context to do the heavy lifting. fetch(_:) returns an array of managed objects meeting the criteria specified by the fetch request.*/
do {
excercisess = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. (error), (error.userInfo)")
}
}
ios swift xcode
add a comment |
There is an option in my app to add new excercises (via user input), i've managed to set the alert and add feature, but I can't save the data added and let it be persistent after closure and that.
//
// ExcerciseListViewController.swift
// OneRepMax
//
// Created by Mauro Garcia on 17/01/2019.
// Copyright © 2019 Mauro Garcia. All rights reserved.
//
import Foundation
import UIKit
import CoreData
class ExcerciseListViewController: UIViewController, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
title = "Excercises"
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
// This view controller itself will provide the delegate methods and row data for the table view.
tableView.delegate = self
tableView.dataSource = self
}
@IBOutlet weak var tableView: UITableView!
// Add a new excercise
@IBAction func addExcercise(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "New Excercise", message: "Add a new excercise", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
guard let textField = alert.textFields?.first,
let nameToSave = textField.text
else {
return
}
print(nameToSave)
self.excercises.append(nameToSave)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
alert.addTextField()
alert.addAction(saveAction)
alert.addAction(cancelAction)
present(alert, animated: true)
}
var excercises: [String] =
}
// MARK: - UITableViewDataSource
extension ExcerciseListViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
print(excercises.count)
return excercises.count
}
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
let cell =
tableView.dequeueReusableCell(withIdentifier: "Cell",
for: indexPath)
cell.textLabel?.text = excercises[indexPath.row]
return cell
}
// What happens when user touch an excercise
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let excerciseChosen = "(excercises[indexPath.row])"
goBackToOneButtonTapped((Any).self)
excUserChose = excerciseChosen
print(excUserChose)
print("You tapped cell number (indexPath.row).")
print(excerciseChosen)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "changeText"), object: nil)
}
func goBackToOneButtonTapped(_ sender: Any) {
performSegue(withIdentifier: "unwindToViewController", sender: self)
}
}
// TODO: save user input
In my AppDelegate.swift
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded the store for the
application to it. This property is optional since there are legitimate
error conditions that could cause the creation of the store to fail.
*/
let container = NSPersistentContainer(name: "OneRepMax")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error (error), (error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error (nserror), (nserror.userInfo)")
}
}
}
I want to -when the user press "Save"- to save the data to be accesible after.
I've tried to implement CoreData but I have failed trying. Don't know what I'm doing wrong.
EDIT:
Code for adding and saving input
var excercisess: [NSManagedObject] =
@IBAction func addExcercise(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "New Excercise", message: "Add a new excercise", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
guard let textField = alert.textFields?.first,
let nameToSave = textField.text
else {
return
}
self.save(name: nameToSave)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
alert.addTextField()
alert.addAction(saveAction)
alert.addAction(cancelAction)
present(alert, animated: true)
}
func save(name: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
/*1.
Before you can save or retrieve anything from your Core Data store, you first need to get your hands on an NSManagedObjectContext. You can consider a managed object context as an in-memory “scratchpad” for working with managed objects.
Think of saving a new managed object to Core Data as a two-step process: first, you insert a new managed object into a managed object context; then, after you’re happy with your shiny new managed object, you “commit” the changes in your managed object context to save it to disk.
Xcode has already generated a managed object context as part of the new project’s template. Remember, this only happens if you check the Use Core Data checkbox at the beginning. This default managed object context lives as a property of the NSPersistentContainer in the application delegate. To access it, you first get a reference to the app delegate.
*/
let managedContext = appDelegate.persistentContainer.viewContext
/*
An NSEntityDescription object is associated with a specific class instance
Class
NSEntityDescription
A description of an entity in Core Data.
Retrieving an Entity with a Given Name here person
*/
let entity = NSEntityDescription.entity(forEntityName: "Excercise", in: managedContext)!
/*
Initializes a managed object and inserts it into the specified managed object context.
init(entity: NSEntityDescription,
insertInto context: NSManagedObjectContext?)
*/
let excercises = NSManagedObject(entity: entity, insertInto: managedContext)
//we can simply create person object this way also.
// let excercise = Excercise(context: managedContext)
/*
With an NSManagedObject in hand, you set the name attribute using key-value coding. You must spell the KVC key (name in this case) exactly as it appears in your Data Model
*/
excercises.setValue(name, forKeyPath: "name")
/*
You commit your changes to person and save to disk by calling save on the managed object context. Note save can throw an error, which is why you call it using the try keyword within a do-catch block. Finally, insert the new managed object into the people array so it shows up when the table view reloads.
*/
do {
try managedContext.save()
excercisess.append(excercises)
tableView.reloadData()
print("SAVED")
} catch let error as NSError {
print("Could not save. (error), (error.userInfo)")
}
}
And the code for fetching:
func fetchAllExcercises(){
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
/*Before you can do anything with Core Data, you need a managed object context. */
let managedContext = appDelegate.persistentContainer.viewContext
/*As the name suggests, NSFetchRequest is the class responsible for fetching from Core Data.
Initializing a fetch request with init(entityName:), fetches all objects of a particular entity. This is what you do here to fetch all Person entities.
*/
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Excercise")
/*You hand the fetch request over to the managed object context to do the heavy lifting. fetch(_:) returns an array of managed objects meeting the criteria specified by the fetch request.*/
do {
excercisess = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. (error), (error.userInfo)")
}
}
ios swift xcode
Did you check the "Use Core Data" box when you created the project? If so, did you create an Exercise entity?
– Steve Robertson
Jan 19 at 0:32
@SteveRobertson Hi! nope, but I added it by copying the code from another project (I created one with Use Core Data) to AppDelegate and that. As you can see. I have an Entity "Excercise" with only one attribute "nameOfExcercise" of type String.
– Mauro Garcia
Jan 19 at 0:35
Did you also create an xcdatamodeld file?
– Steve Robertson
Jan 19 at 0:42
add a comment |
There is an option in my app to add new excercises (via user input), i've managed to set the alert and add feature, but I can't save the data added and let it be persistent after closure and that.
//
// ExcerciseListViewController.swift
// OneRepMax
//
// Created by Mauro Garcia on 17/01/2019.
// Copyright © 2019 Mauro Garcia. All rights reserved.
//
import Foundation
import UIKit
import CoreData
class ExcerciseListViewController: UIViewController, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
title = "Excercises"
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
// This view controller itself will provide the delegate methods and row data for the table view.
tableView.delegate = self
tableView.dataSource = self
}
@IBOutlet weak var tableView: UITableView!
// Add a new excercise
@IBAction func addExcercise(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "New Excercise", message: "Add a new excercise", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
guard let textField = alert.textFields?.first,
let nameToSave = textField.text
else {
return
}
print(nameToSave)
self.excercises.append(nameToSave)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
alert.addTextField()
alert.addAction(saveAction)
alert.addAction(cancelAction)
present(alert, animated: true)
}
var excercises: [String] =
}
// MARK: - UITableViewDataSource
extension ExcerciseListViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
print(excercises.count)
return excercises.count
}
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
let cell =
tableView.dequeueReusableCell(withIdentifier: "Cell",
for: indexPath)
cell.textLabel?.text = excercises[indexPath.row]
return cell
}
// What happens when user touch an excercise
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let excerciseChosen = "(excercises[indexPath.row])"
goBackToOneButtonTapped((Any).self)
excUserChose = excerciseChosen
print(excUserChose)
print("You tapped cell number (indexPath.row).")
print(excerciseChosen)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "changeText"), object: nil)
}
func goBackToOneButtonTapped(_ sender: Any) {
performSegue(withIdentifier: "unwindToViewController", sender: self)
}
}
// TODO: save user input
In my AppDelegate.swift
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded the store for the
application to it. This property is optional since there are legitimate
error conditions that could cause the creation of the store to fail.
*/
let container = NSPersistentContainer(name: "OneRepMax")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error (error), (error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error (nserror), (nserror.userInfo)")
}
}
}
I want to -when the user press "Save"- to save the data to be accesible after.
I've tried to implement CoreData but I have failed trying. Don't know what I'm doing wrong.
EDIT:
Code for adding and saving input
var excercisess: [NSManagedObject] =
@IBAction func addExcercise(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "New Excercise", message: "Add a new excercise", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
guard let textField = alert.textFields?.first,
let nameToSave = textField.text
else {
return
}
self.save(name: nameToSave)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
alert.addTextField()
alert.addAction(saveAction)
alert.addAction(cancelAction)
present(alert, animated: true)
}
func save(name: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
/*1.
Before you can save or retrieve anything from your Core Data store, you first need to get your hands on an NSManagedObjectContext. You can consider a managed object context as an in-memory “scratchpad” for working with managed objects.
Think of saving a new managed object to Core Data as a two-step process: first, you insert a new managed object into a managed object context; then, after you’re happy with your shiny new managed object, you “commit” the changes in your managed object context to save it to disk.
Xcode has already generated a managed object context as part of the new project’s template. Remember, this only happens if you check the Use Core Data checkbox at the beginning. This default managed object context lives as a property of the NSPersistentContainer in the application delegate. To access it, you first get a reference to the app delegate.
*/
let managedContext = appDelegate.persistentContainer.viewContext
/*
An NSEntityDescription object is associated with a specific class instance
Class
NSEntityDescription
A description of an entity in Core Data.
Retrieving an Entity with a Given Name here person
*/
let entity = NSEntityDescription.entity(forEntityName: "Excercise", in: managedContext)!
/*
Initializes a managed object and inserts it into the specified managed object context.
init(entity: NSEntityDescription,
insertInto context: NSManagedObjectContext?)
*/
let excercises = NSManagedObject(entity: entity, insertInto: managedContext)
//we can simply create person object this way also.
// let excercise = Excercise(context: managedContext)
/*
With an NSManagedObject in hand, you set the name attribute using key-value coding. You must spell the KVC key (name in this case) exactly as it appears in your Data Model
*/
excercises.setValue(name, forKeyPath: "name")
/*
You commit your changes to person and save to disk by calling save on the managed object context. Note save can throw an error, which is why you call it using the try keyword within a do-catch block. Finally, insert the new managed object into the people array so it shows up when the table view reloads.
*/
do {
try managedContext.save()
excercisess.append(excercises)
tableView.reloadData()
print("SAVED")
} catch let error as NSError {
print("Could not save. (error), (error.userInfo)")
}
}
And the code for fetching:
func fetchAllExcercises(){
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
/*Before you can do anything with Core Data, you need a managed object context. */
let managedContext = appDelegate.persistentContainer.viewContext
/*As the name suggests, NSFetchRequest is the class responsible for fetching from Core Data.
Initializing a fetch request with init(entityName:), fetches all objects of a particular entity. This is what you do here to fetch all Person entities.
*/
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Excercise")
/*You hand the fetch request over to the managed object context to do the heavy lifting. fetch(_:) returns an array of managed objects meeting the criteria specified by the fetch request.*/
do {
excercisess = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. (error), (error.userInfo)")
}
}
ios swift xcode
There is an option in my app to add new excercises (via user input), i've managed to set the alert and add feature, but I can't save the data added and let it be persistent after closure and that.
//
// ExcerciseListViewController.swift
// OneRepMax
//
// Created by Mauro Garcia on 17/01/2019.
// Copyright © 2019 Mauro Garcia. All rights reserved.
//
import Foundation
import UIKit
import CoreData
class ExcerciseListViewController: UIViewController, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
title = "Excercises"
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
// This view controller itself will provide the delegate methods and row data for the table view.
tableView.delegate = self
tableView.dataSource = self
}
@IBOutlet weak var tableView: UITableView!
// Add a new excercise
@IBAction func addExcercise(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "New Excercise", message: "Add a new excercise", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
guard let textField = alert.textFields?.first,
let nameToSave = textField.text
else {
return
}
print(nameToSave)
self.excercises.append(nameToSave)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
alert.addTextField()
alert.addAction(saveAction)
alert.addAction(cancelAction)
present(alert, animated: true)
}
var excercises: [String] =
}
// MARK: - UITableViewDataSource
extension ExcerciseListViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
print(excercises.count)
return excercises.count
}
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
let cell =
tableView.dequeueReusableCell(withIdentifier: "Cell",
for: indexPath)
cell.textLabel?.text = excercises[indexPath.row]
return cell
}
// What happens when user touch an excercise
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let excerciseChosen = "(excercises[indexPath.row])"
goBackToOneButtonTapped((Any).self)
excUserChose = excerciseChosen
print(excUserChose)
print("You tapped cell number (indexPath.row).")
print(excerciseChosen)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "changeText"), object: nil)
}
func goBackToOneButtonTapped(_ sender: Any) {
performSegue(withIdentifier: "unwindToViewController", sender: self)
}
}
// TODO: save user input
In my AppDelegate.swift
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded the store for the
application to it. This property is optional since there are legitimate
error conditions that could cause the creation of the store to fail.
*/
let container = NSPersistentContainer(name: "OneRepMax")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error (error), (error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error (nserror), (nserror.userInfo)")
}
}
}
I want to -when the user press "Save"- to save the data to be accesible after.
I've tried to implement CoreData but I have failed trying. Don't know what I'm doing wrong.
EDIT:
Code for adding and saving input
var excercisess: [NSManagedObject] =
@IBAction func addExcercise(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "New Excercise", message: "Add a new excercise", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
guard let textField = alert.textFields?.first,
let nameToSave = textField.text
else {
return
}
self.save(name: nameToSave)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
alert.addTextField()
alert.addAction(saveAction)
alert.addAction(cancelAction)
present(alert, animated: true)
}
func save(name: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
/*1.
Before you can save or retrieve anything from your Core Data store, you first need to get your hands on an NSManagedObjectContext. You can consider a managed object context as an in-memory “scratchpad” for working with managed objects.
Think of saving a new managed object to Core Data as a two-step process: first, you insert a new managed object into a managed object context; then, after you’re happy with your shiny new managed object, you “commit” the changes in your managed object context to save it to disk.
Xcode has already generated a managed object context as part of the new project’s template. Remember, this only happens if you check the Use Core Data checkbox at the beginning. This default managed object context lives as a property of the NSPersistentContainer in the application delegate. To access it, you first get a reference to the app delegate.
*/
let managedContext = appDelegate.persistentContainer.viewContext
/*
An NSEntityDescription object is associated with a specific class instance
Class
NSEntityDescription
A description of an entity in Core Data.
Retrieving an Entity with a Given Name here person
*/
let entity = NSEntityDescription.entity(forEntityName: "Excercise", in: managedContext)!
/*
Initializes a managed object and inserts it into the specified managed object context.
init(entity: NSEntityDescription,
insertInto context: NSManagedObjectContext?)
*/
let excercises = NSManagedObject(entity: entity, insertInto: managedContext)
//we can simply create person object this way also.
// let excercise = Excercise(context: managedContext)
/*
With an NSManagedObject in hand, you set the name attribute using key-value coding. You must spell the KVC key (name in this case) exactly as it appears in your Data Model
*/
excercises.setValue(name, forKeyPath: "name")
/*
You commit your changes to person and save to disk by calling save on the managed object context. Note save can throw an error, which is why you call it using the try keyword within a do-catch block. Finally, insert the new managed object into the people array so it shows up when the table view reloads.
*/
do {
try managedContext.save()
excercisess.append(excercises)
tableView.reloadData()
print("SAVED")
} catch let error as NSError {
print("Could not save. (error), (error.userInfo)")
}
}
And the code for fetching:
func fetchAllExcercises(){
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
/*Before you can do anything with Core Data, you need a managed object context. */
let managedContext = appDelegate.persistentContainer.viewContext
/*As the name suggests, NSFetchRequest is the class responsible for fetching from Core Data.
Initializing a fetch request with init(entityName:), fetches all objects of a particular entity. This is what you do here to fetch all Person entities.
*/
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Excercise")
/*You hand the fetch request over to the managed object context to do the heavy lifting. fetch(_:) returns an array of managed objects meeting the criteria specified by the fetch request.*/
do {
excercisess = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. (error), (error.userInfo)")
}
}
ios swift xcode
ios swift xcode
edited Jan 19 at 12:43
Mauro Garcia
asked Jan 18 at 23:27
Mauro GarciaMauro Garcia
11
11
Did you check the "Use Core Data" box when you created the project? If so, did you create an Exercise entity?
– Steve Robertson
Jan 19 at 0:32
@SteveRobertson Hi! nope, but I added it by copying the code from another project (I created one with Use Core Data) to AppDelegate and that. As you can see. I have an Entity "Excercise" with only one attribute "nameOfExcercise" of type String.
– Mauro Garcia
Jan 19 at 0:35
Did you also create an xcdatamodeld file?
– Steve Robertson
Jan 19 at 0:42
add a comment |
Did you check the "Use Core Data" box when you created the project? If so, did you create an Exercise entity?
– Steve Robertson
Jan 19 at 0:32
@SteveRobertson Hi! nope, but I added it by copying the code from another project (I created one with Use Core Data) to AppDelegate and that. As you can see. I have an Entity "Excercise" with only one attribute "nameOfExcercise" of type String.
– Mauro Garcia
Jan 19 at 0:35
Did you also create an xcdatamodeld file?
– Steve Robertson
Jan 19 at 0:42
Did you check the "Use Core Data" box when you created the project? If so, did you create an Exercise entity?
– Steve Robertson
Jan 19 at 0:32
Did you check the "Use Core Data" box when you created the project? If so, did you create an Exercise entity?
– Steve Robertson
Jan 19 at 0:32
@SteveRobertson Hi! nope, but I added it by copying the code from another project (I created one with Use Core Data) to AppDelegate and that. As you can see. I have an Entity "Excercise" with only one attribute "nameOfExcercise" of type String.
– Mauro Garcia
Jan 19 at 0:35
@SteveRobertson Hi! nope, but I added it by copying the code from another project (I created one with Use Core Data) to AppDelegate and that. As you can see. I have an Entity "Excercise" with only one attribute "nameOfExcercise" of type String.
– Mauro Garcia
Jan 19 at 0:35
Did you also create an xcdatamodeld file?
– Steve Robertson
Jan 19 at 0:42
Did you also create an xcdatamodeld file?
– Steve Robertson
Jan 19 at 0:42
add a comment |
1 Answer
1
active
oldest
votes
There are several things that you still need once you have the xcdatamodeld file set up.
Your array should be an array of your CoreData entity.
var exercises = [Exercise]()
You need to create an instance of the managed object context.
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
Then you will need to use that instance to create new objects in the array, save the new objects and fetch them. Have a go at finding out how to create those functions (Youtube, web articles) and then see if you still have questions.
I managed to get the save action work, but now when I make the function for fetching data it terminate my app.
– Mauro Garcia
Jan 19 at 11:04
What does the debug console say regarding the error? Can you post your code for adding, saving and fetching your data?
– Steve Robertson
Jan 19 at 11:12
Added. When i include fetchAllExcercises() into the viewDidLoad() it crashes when I click the button to go into the tableView and says: "2019-01-19 13:44:18.341344+0100 OneRepMax[24792:1011141] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'"
– Mauro Garcia
Jan 19 at 12:46
Do you have a Cocoa Touch class file of type UITableViewCell? This would be the file that the textLabel is connected to and this would be the class you would assign your table cell to in the Storyboard. And your cellForRowAt function would read let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ExerciseCell
– Steve Robertson
Jan 19 at 14:40
No, I don't have a Cocoa Touch class file. Edit: YES, it's a Cocoa Touch. But not with UITableViewCell.
– Mauro Garcia
Jan 19 at 18:34
|
show 3 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54262697%2fsave-user-input-data-of-uitableview%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
There are several things that you still need once you have the xcdatamodeld file set up.
Your array should be an array of your CoreData entity.
var exercises = [Exercise]()
You need to create an instance of the managed object context.
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
Then you will need to use that instance to create new objects in the array, save the new objects and fetch them. Have a go at finding out how to create those functions (Youtube, web articles) and then see if you still have questions.
I managed to get the save action work, but now when I make the function for fetching data it terminate my app.
– Mauro Garcia
Jan 19 at 11:04
What does the debug console say regarding the error? Can you post your code for adding, saving and fetching your data?
– Steve Robertson
Jan 19 at 11:12
Added. When i include fetchAllExcercises() into the viewDidLoad() it crashes when I click the button to go into the tableView and says: "2019-01-19 13:44:18.341344+0100 OneRepMax[24792:1011141] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'"
– Mauro Garcia
Jan 19 at 12:46
Do you have a Cocoa Touch class file of type UITableViewCell? This would be the file that the textLabel is connected to and this would be the class you would assign your table cell to in the Storyboard. And your cellForRowAt function would read let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ExerciseCell
– Steve Robertson
Jan 19 at 14:40
No, I don't have a Cocoa Touch class file. Edit: YES, it's a Cocoa Touch. But not with UITableViewCell.
– Mauro Garcia
Jan 19 at 18:34
|
show 3 more comments
There are several things that you still need once you have the xcdatamodeld file set up.
Your array should be an array of your CoreData entity.
var exercises = [Exercise]()
You need to create an instance of the managed object context.
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
Then you will need to use that instance to create new objects in the array, save the new objects and fetch them. Have a go at finding out how to create those functions (Youtube, web articles) and then see if you still have questions.
I managed to get the save action work, but now when I make the function for fetching data it terminate my app.
– Mauro Garcia
Jan 19 at 11:04
What does the debug console say regarding the error? Can you post your code for adding, saving and fetching your data?
– Steve Robertson
Jan 19 at 11:12
Added. When i include fetchAllExcercises() into the viewDidLoad() it crashes when I click the button to go into the tableView and says: "2019-01-19 13:44:18.341344+0100 OneRepMax[24792:1011141] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'"
– Mauro Garcia
Jan 19 at 12:46
Do you have a Cocoa Touch class file of type UITableViewCell? This would be the file that the textLabel is connected to and this would be the class you would assign your table cell to in the Storyboard. And your cellForRowAt function would read let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ExerciseCell
– Steve Robertson
Jan 19 at 14:40
No, I don't have a Cocoa Touch class file. Edit: YES, it's a Cocoa Touch. But not with UITableViewCell.
– Mauro Garcia
Jan 19 at 18:34
|
show 3 more comments
There are several things that you still need once you have the xcdatamodeld file set up.
Your array should be an array of your CoreData entity.
var exercises = [Exercise]()
You need to create an instance of the managed object context.
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
Then you will need to use that instance to create new objects in the array, save the new objects and fetch them. Have a go at finding out how to create those functions (Youtube, web articles) and then see if you still have questions.
There are several things that you still need once you have the xcdatamodeld file set up.
Your array should be an array of your CoreData entity.
var exercises = [Exercise]()
You need to create an instance of the managed object context.
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
Then you will need to use that instance to create new objects in the array, save the new objects and fetch them. Have a go at finding out how to create those functions (Youtube, web articles) and then see if you still have questions.
answered Jan 19 at 1:16
Steve RobertsonSteve Robertson
1499
1499
I managed to get the save action work, but now when I make the function for fetching data it terminate my app.
– Mauro Garcia
Jan 19 at 11:04
What does the debug console say regarding the error? Can you post your code for adding, saving and fetching your data?
– Steve Robertson
Jan 19 at 11:12
Added. When i include fetchAllExcercises() into the viewDidLoad() it crashes when I click the button to go into the tableView and says: "2019-01-19 13:44:18.341344+0100 OneRepMax[24792:1011141] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'"
– Mauro Garcia
Jan 19 at 12:46
Do you have a Cocoa Touch class file of type UITableViewCell? This would be the file that the textLabel is connected to and this would be the class you would assign your table cell to in the Storyboard. And your cellForRowAt function would read let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ExerciseCell
– Steve Robertson
Jan 19 at 14:40
No, I don't have a Cocoa Touch class file. Edit: YES, it's a Cocoa Touch. But not with UITableViewCell.
– Mauro Garcia
Jan 19 at 18:34
|
show 3 more comments
I managed to get the save action work, but now when I make the function for fetching data it terminate my app.
– Mauro Garcia
Jan 19 at 11:04
What does the debug console say regarding the error? Can you post your code for adding, saving and fetching your data?
– Steve Robertson
Jan 19 at 11:12
Added. When i include fetchAllExcercises() into the viewDidLoad() it crashes when I click the button to go into the tableView and says: "2019-01-19 13:44:18.341344+0100 OneRepMax[24792:1011141] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'"
– Mauro Garcia
Jan 19 at 12:46
Do you have a Cocoa Touch class file of type UITableViewCell? This would be the file that the textLabel is connected to and this would be the class you would assign your table cell to in the Storyboard. And your cellForRowAt function would read let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ExerciseCell
– Steve Robertson
Jan 19 at 14:40
No, I don't have a Cocoa Touch class file. Edit: YES, it's a Cocoa Touch. But not with UITableViewCell.
– Mauro Garcia
Jan 19 at 18:34
I managed to get the save action work, but now when I make the function for fetching data it terminate my app.
– Mauro Garcia
Jan 19 at 11:04
I managed to get the save action work, but now when I make the function for fetching data it terminate my app.
– Mauro Garcia
Jan 19 at 11:04
What does the debug console say regarding the error? Can you post your code for adding, saving and fetching your data?
– Steve Robertson
Jan 19 at 11:12
What does the debug console say regarding the error? Can you post your code for adding, saving and fetching your data?
– Steve Robertson
Jan 19 at 11:12
Added. When i include fetchAllExcercises() into the viewDidLoad() it crashes when I click the button to go into the tableView and says: "2019-01-19 13:44:18.341344+0100 OneRepMax[24792:1011141] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'"
– Mauro Garcia
Jan 19 at 12:46
Added. When i include fetchAllExcercises() into the viewDidLoad() it crashes when I click the button to go into the tableView and says: "2019-01-19 13:44:18.341344+0100 OneRepMax[24792:1011141] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'"
– Mauro Garcia
Jan 19 at 12:46
Do you have a Cocoa Touch class file of type UITableViewCell? This would be the file that the textLabel is connected to and this would be the class you would assign your table cell to in the Storyboard. And your cellForRowAt function would read let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ExerciseCell
– Steve Robertson
Jan 19 at 14:40
Do you have a Cocoa Touch class file of type UITableViewCell? This would be the file that the textLabel is connected to and this would be the class you would assign your table cell to in the Storyboard. And your cellForRowAt function would read let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ExerciseCell
– Steve Robertson
Jan 19 at 14:40
No, I don't have a Cocoa Touch class file. Edit: YES, it's a Cocoa Touch. But not with UITableViewCell.
– Mauro Garcia
Jan 19 at 18:34
No, I don't have a Cocoa Touch class file. Edit: YES, it's a Cocoa Touch. But not with UITableViewCell.
– Mauro Garcia
Jan 19 at 18:34
|
show 3 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54262697%2fsave-user-input-data-of-uitableview%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Did you check the "Use Core Data" box when you created the project? If so, did you create an Exercise entity?
– Steve Robertson
Jan 19 at 0:32
@SteveRobertson Hi! nope, but I added it by copying the code from another project (I created one with Use Core Data) to AppDelegate and that. As you can see. I have an Entity "Excercise" with only one attribute "nameOfExcercise" of type String.
– Mauro Garcia
Jan 19 at 0:35
Did you also create an xcdatamodeld file?
– Steve Robertson
Jan 19 at 0:42