I want to fetch contact name and number in same cell but it fetches name in first cell and number in second cell i have added my entire coding here....
import UIKit
import AddressBook
import CoreData
class ContactViewController: UIViewController,CNContactPickerDelegate,UITableViewDelegate,UITableViewDataSource{
var contactStore = CNContactStore()
var mycontact:CNContactStore!
var myContacts = [CNContact]()
var names = [NSManagedObject]()
var numbers = [NSManagedObject]()
var yourcont:NSMutableArray = NSMutableArray()
#IBOutlet weak var FirstTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
navigationController!.navigationBar.barTintColor = UIColor.blueColor()
navigationController!.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
// Do any additional setup after loading the view.
}
#IBAction func AddButtonTapped(sender: AnyObject) {
let alert = UIAlertController(title: "New Contact",
message: "Add a new contact",
preferredStyle: .Alert)
let saveAction = UIAlertAction(title: "Save",
style: .Default,
handler: { (action:UIAlertAction) -> Void in
let textField = alert.textFields![0] as UITextField
self.saveName(textField.text!)
let sedfield = alert.textFields![1] as UITextField
self.saveNum(sedfield.text!)
self.FirstTableView.reloadData()
})
let cancelAction = UIAlertAction(title: "Cancel",
style: .Default) { (action: UIAlertAction) -> Void in
}
alert.addTextFieldWithConfigurationHandler {
(textField: UITextField) -> Void in
textField.placeholder = "Enter Your Name"
}
alert.addTextFieldWithConfigurationHandler {
(sedfield: UITextField) -> Void in
sedfield.placeholder = "Enter your Number"
}
alert.addAction(saveAction)
alert.addAction(cancelAction)
presentViewController(alert,
animated: true,
completion: nil)
}
func saveName(name: String) {
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("Person",
inManagedObjectContext:managedContext)
let person = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext: managedContext)
person.setValue(name, forKey: "name")
do {
try managedContext.save()
names.append(person)
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
func saveNum(name: String) {
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("Person",
inManagedObjectContext:managedContext)
let person = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext: managedContext)
person.setValue(name, forKey: "number")
do {
try managedContext.save()
numbers.append(person)
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
#IBAction func LeftTapped(sender: AnyObject) {
let appDelegate:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.centerContainer?.toggleDrawerSide(MMDrawerSide.Left, animated: true, completion: nil)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(section == 0) {
return names.count
}
return numbers.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ContactCell") as! TableViewCell
let personname = names[indexPath.row]
cell.ConName.text = personname.valueForKey("name") as? String
let personnum = numbers[indexPath.row]
cell.ConNumber.text = personnum.valueForKey("number") as? String
return cell
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool
{
return true
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
{
if editingStyle == .Delete
{
numbers.removeAtIndex(indexPath.row)
tableView.reloadData()
}
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Person")
do {
let results =
try managedContext.executeFetchRequest(fetchRequest)
names = results as! [NSManagedObject]
numbers = results as! [NSManagedObject]
print(results)
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
Choose Table View Cell on Storyboard and set Style with Subtitle
Related
I save data from MovieDetailViewController in coreData. I try to access coreData data from another controller. When I save the data to coreData and switch to another controller where I output the result in tableView, it doesn't show me the newly saved names there. When I delete the background and reopen it then it shows me the last saved data.
I need something similar to the tableView method tableView.reloadData().
class MovieDetailViewController: UIViewController {
var coreDataMovieName: [NSManagedObject] = []
var movie: Movie!
var detailsImageView: UIImage!
var movieName = ""
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = movie.title
//Detalebshi Photos gamochena
if let posterPath = movie.posterPath {
TMDBClient.downloadPosterImage(path: posterPath) { (data, error) in
guard let data = data else {
return
}
let image = UIImage(data: data)
self.imageView.image = image
self.detailsImageView = image
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Favorite")
do {
coreDataMovieName = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
func save(name: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Favorite", in: managedContext)!
let person = NSManagedObject(entity: entity, insertInto: managedContext)
person.setValue(name, forKeyPath: "movieName")
do {
try managedContext.save()
coreDataMovieName.append(person)
print("saved \(person)")
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
#IBAction func coreDataFavoritesBtnTapped(_ sender: Any) {
save(name: movieName)
}
}
A controller where I try to access Core Data:
class CoreDataFavoritesViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var movie: [NSManagedObject] = []
override func viewDidLoad() {
super.viewDidLoad()
title = "The List"
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
tableView.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Favorite")
do {
movie = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
}
// MARK: - UITableViewDataSource
extension CoreDataFavoritesViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return movie.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let person = movie[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = person.value(forKeyPath: "movieName") as? String
return cell
}
}
You are appending Data after context save
coreDataMovieName.append(person)
do it before
try managedContext.save()
I have an app that takes in user input that is stored in core data. To simplify things, I combined 5 strings from the user inputs, separated them with a comma and then this long string is stored in core data as 1 entity. The comma is separating the individual 'strings' is what makes it a CSV.
The tableview does what it's supposed to do, but the problem lies when I try to export the coredata entries as a csv. I realise that I am not making use of the fetchedStatsArray as I should and thus it is empty. I tried appending the array with NSManagedObject but none of that work. Is there a way to fix this, such that my fetchedStatsArray is filled? If not, is there another way to make sure that when the csv is generated, it will contain all the data from coredata?
Here is most of my code:
import UIKit
import CoreData
import MessageUI
class HistoryController: UITableViewController, NSFetchedResultsControllerDelegate {
let cellId = "cellId"
var fetchedStatsArray: [NSManagedObject] = []
fileprivate lazy var fetchedResultsController: NSFetchedResultsController<AlarmItem> = {
//create fetch request
let fetchRequest: NSFetchRequest<AlarmItem> = AlarmItem.fetchRequest()
//configure fetch request
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "alarmAttributes", ascending: true)]
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
fetchedResultsController.delegate = self
return fetchedResultsController
}()
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch(type) {
case .insert:
if let indexPath = newIndexPath {
tableView.insertRows(at: [indexPath], with: .fade)
}
break;
case .delete:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
break;
case .update:
//this is mostlikely where the problem lies
//self.tableView.reloadData()
if let indexPath = indexPath, let cell = tableView.cellForRow(at: indexPath) {
configureCell(cell, at: indexPath)
}
break;
case .move:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
if let newIndexPath = newIndexPath {
tableView.insertRows(at: [newIndexPath], with: .fade)
}
break;
#unknown default:
print("Something odd is happening")
}
}
override func viewDidLoad() {
super.viewDidLoad()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
do {
try fetchedResultsController.performFetch()
} catch let err as NSError {
print("Failed to fetch items", err)
}
}
#objc func addAlarmItem(_ sender: AnyObject) {
let alertController = UIAlertController(title: "Add New Item", message: "Please fill in the blanks", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
//combined string of attributes
let myStrings: [String] = alertController.textFields!.compactMap { $0.text }
let myText = myStrings.joined(separator: ",")
self.save(myText)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)
alertController.addTextField { (textField) in
textField.placeholder = "Enter Name of Engineer"
}
alertController.addTextField { (textField) in
textField.placeholder = "Enter Date of Alarm in DD/MM/YYYY"
}
alertController.addTextField { (textField) in
textField.placeholder = "Enter Time of Alarm in 24h (eg: 2300)"
}
alertController.addTextField { (textField) in
textField.placeholder = "Please indicate True/False (type True or False)"
}
alertController.addTextField { (textField) in
textField.placeholder = "Insert comments (if any), or NIL"
}
if let popoverController = alertController.popoverPresentationController {
popoverController.sourceView = self.view;
popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0.0, height: 0.0)
popoverController.permittedArrowDirections = []
popoverController.barButtonItem = self.navigationItem.leftBarButtonItem
}
self.present(alertController, animated: true, completion: nil)
}
func save(_ itemName: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "AlarmItem", in: managedContext)!
let item = NSManagedObject(entity: entity, insertInto: managedContext)
item.setValue(itemName, forKey: "alarmAttributes")
do {
try managedContext.save()
tableView.reloadData()
} catch let err as NSError {
print("Failed to save an item", err)
}
}
#objc func exportCSV(_ sender: AnyObject) {
exportDatabase()
}
func exportDatabase() {
let exportString = createExportString()
saveAndExport(exportString: exportString)
}
func saveAndExport(exportString: String) {
let exportFilePath = NSTemporaryDirectory() + "itemlist.csv"
let exportFileUrl = NSURL(fileURLWithPath: exportFilePath)
FileManager.default.createFile(atPath: exportFilePath, contents: NSData() as Data, attributes: nil)
var fileHandle: FileHandle? = nil
do {
fileHandle = try FileHandle(forUpdating: exportFileUrl as URL)
} catch {
print("filehandle has error")
}
if fileHandle != nil {
fileHandle!.seekToEndOfFile()
let csvData = exportString.data(using: String.Encoding.utf8, allowLossyConversion: false)
fileHandle!.write(csvData!)
fileHandle!.closeFile()
let firstActivityItem = NSURL(fileURLWithPath: exportFilePath)
let activityViewController : UIActivityViewController = UIActivityViewController(activityItems: [firstActivityItem], applicationActivities: nil)
activityViewController.excludedActivityTypes = [
UIActivity.ActivityType.assignToContact,
UIActivity.ActivityType.saveToCameraRoll,
UIActivity.ActivityType.postToFlickr,
UIActivity.ActivityType.postToVimeo,
UIActivity.ActivityType.postToTencentWeibo
]
activityViewController.popoverPresentationController?.sourceView = self.view
activityViewController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection()
activityViewController.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
self.present(activityViewController, animated: true, completion: nil)
}
}
func createExportString() -> String {
var alarmAttributes: String?
var export: String = NSLocalizedString("Engineer Name,Date of Alarm,Time of Alarm,True or False,Engineer Comments \n", comment: "")
for (index, AlarmItem) in fetchedStatsArray.enumerated() {
if index <= fetchedStatsArray.count - 1 {
alarmAttributes = AlarmItem.value(forKey: "alarmAttributes") as! String?
let alarmAttributeStrings = alarmAttributes
export += "\(alarmAttributeStrings ?? "0") \n"
}
}
print("the app will now print: \(export) ")
return export
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
let sectionInfo = fetchedResultsController.sections![section]
return sectionInfo.numberOfObjects
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let alarmItem = fetchedResultsController.object(at: indexPath) as NSManagedObject
cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
return cell
}
func tableView(_ tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
return true
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
guard editingStyle == .delete else { return }
//fetch
let toBeDeleted = fetchedResultsController.object(at: indexPath)
//delete
fetchedResultsController.managedObjectContext.delete(toBeDeleted)
do {
try fetchedResultsController.managedObjectContext.save()
} catch let err as NSError {
print("failed to save item", err)
}
}
func tableView(_tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "AlarmItem", for: indexPath)
configureCell(cell, at: indexPath)
return cell
}
func configureCell(_ cell: UITableViewCell, at indexPath: IndexPath) {
let alarmItem = fetchedResultsController.object(at: indexPath)
//configure cell
cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
}
}
Basically I have an app that takes in user input (in 5 textfields in an alertcontroller) that are all concatenated in to a string to be in a form that looks like it is a row in a csv file and stored to coredata as a entity. This entity will then be displayed in a tableview. I would like to be able to export the csv file to email it elsewhere. All this will be done in the iOS device itself.
I have looked on this website and other websites but to no avail. A large majority of the example code makes use of outdated versions of swift and xcode.
class ViewController: UITableViewController, NSFetchedResultsControllerDelegate {
let cellId = "cellId"
fileprivate lazy var fetchedResultsController: NSFetchedResultsController<AlarmItem> = {
//create fetch request
let fetchRequest: NSFetchRequest<AlarmItem> = AlarmItem.fetchRequest()
//configure fetch request
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "alarmAttributes", ascending: true)]
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
fetchedResultsController.delegate = self
return fetchedResultsController
}()
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch(type) {
case .insert:
if let indexPath = newIndexPath {
tableView.insertRows(at: [indexPath], with: .fade)
}
break;
case .delete:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
break;
case .update:
if let indexPath = indexPath, let cell = tableView.cellForRow(at: indexPath) {
configureCell(cell, at: indexPath)
}
break;
case .move:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
if let newIndexPath = newIndexPath {
tableView.insertRows(at: [newIndexPath], with: .fade)
}
break;
#unknown default:
print("Something odd is happening")
}
}
override func viewDidLoad() {
super.viewDidLoad()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
do {
try fetchedResultsController.performFetch()
} catch let err as NSError {
print("Failed to fetch items", err)
}
}
#objc func addAlarmItem(_ sender: AnyObject) {
let alertController = UIAlertController(title: "Add New Item", message: "Please fill in the blanks", preferredStyle: .alert)
let saveAction = UIAlertAction(title: "Save", style: .default) { [unowned self] action in
//combined string of attributes
let myStrings: [String] = alertController.textFields!.compactMap { $0.text }
let myText = myStrings.joined(separator: ", ")
self.save(myText)
self.tableView.reloadData()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)
alertController.addTextField { (textField) in
textField.placeholder = "Enter Name of Engineer"
}
alertController.addTextField { (textField) in
textField.placeholder = "Enter Date of Alarm in DD/MM/YYYY"
}
alertController.addTextField { (textField) in
textField.placeholder = "Enter Time of Alarm in 24h (eg: 2300)"
}
alertController.addTextField { (textField) in
textField.placeholder = "Please indicate True/False (type True or False)"
}
alertController.addTextField { (textField) in
textField.placeholder = "Insert comments (if any), or NIL"
}
func save(_ itemName: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "AlarmItem", in: managedContext)!
let item = NSManagedObject(entity: entity, insertInto: managedContext)
item.setValue(itemName, forKey: "alarmAttributes")
do {
try managedContext.save()
tableView.reloadData()
} catch let err as NSError {
print("Failed to save an item", err)
}
}
#objc func exportCSV(_ sender: AnyObject) {
exportDatabase()
}
func exportDatabase() {
let exportString = createExportString()
saveAndExport(exportString: exportString)
}
func saveAndExport(exportString: String) {
let exportFilePath = NSTemporaryDirectory() + "itemlist.csv"
let exportFileUrl = NSURL(fileURLWithPath: exportFilePath)
FileManager.default.createFile(atPath: exportFilePath, contents: NSData() as Data, attributes: nil)
var fileHandle: FileHandle? = nil
do {
fileHandle = try FileHandle(forUpdating: exportFileUrl as URL)
} catch {
print("filehandle has error")
}
if fileHandle != nil {
fileHandle!.seekToEndOfFile()
let csvData = exportString.data(using: String.Encoding.utf8, allowLossyConversion: false)
fileHandle!.write(csvData!)
fileHandle!.closeFile()
let firstActivityItem = NSURL(fileURLWithPath: exportFilePath)
let activityViewController : UIActivityViewController = UIActivityViewController(activityItems: [firstActivityItem], applicationActivities: nil)
activityViewController.excludedActivityTypes = [
UIActivity.ActivityType.assignToContact,
UIActivity.ActivityType.saveToCameraRoll,
UIActivity.ActivityType.postToFlickr,
UIActivity.ActivityType.postToVimeo,
UIActivity.ActivityType.postToTencentWeibo
]
self.present(activityViewController, animated: true, completion: nil)
}
}
func createExportString() -> String {
var alarmAttributes: String?
var export: String = NSLocalizedString("Engineer Name,Date of Alarm,Time of Alarm,True or False,Engineer Comments \n", comment: "")
for (index, AlarmItem) in fetchedStatsArray.enumerated() {
if index <= fetchedStatsArray.count - 1 {
alarmAttributes = AlarmItem.value(forKey: "alarmAttributes") as! String?
let alarmAttributeStrings = alarmAttributes
export += "\(alarmAttributeStrings ?? "0") \n"
}
}
print("the app will now print: \(export) ")
return export
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
let sectionInfo = fetchedResultsController.sections![section]
return sectionInfo.numberOfObjects
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let alarmItem = fetchedResultsController.object(at: indexPath) as NSManagedObject
cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
return cell
}
func tableView(_ tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
return true
}
overr ide func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
guard editingStyle == .delete else { return }
//fetch
let toBeDeleted = fetchedResultsController.object(at: indexPath)
//delete
fetchedResultsController.managedObjectContext.delete(toBeDeleted)
do {
try fetchedResultsController.managedObjectContext.save()
} catch let err as NSError {
print("failed to save item", err)
}
}
func tableView(_tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "AlarmItem", for: indexPath)
configureCell(cell, at: indexPath)
return cell
}
func configureCell(_ cell: UITableViewCell, at indexPath: IndexPath) {
let alarmItem = fetchedResultsController.object(at: indexPath)
//configure cell
cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
}
}
Swift 2: My code saves the data(The item added shows in the list) but as soon as I force close the app it deletes all data?
Sorry for the severe lack of comments but it should be self explanatory. Also i'm quite new to programming so please try to answer in simple terms:)
// ViewController.swift
// Fast Cast
//
// Created by curtis cowan on 31/01/2016.
// Copyright © 2016 Curtis Cowan. All rights reserved.
//
import UIKit
import CoreData
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
var lists = [NSManagedObject]()
#IBOutlet weak var myTableView: UITableView!
#IBAction func addItem(sender: AnyObject) {
let alert = UIAlertController(title: "New List", message: "Add a new list", preferredStyle: .Alert)
let saveAction = UIAlertAction(title: "Save", style: .Default) { (UIAlertAction) -> Void in
let textField = alert.textFields![0] as UITextField
if textField != "" {
self.saveItem(textField.text!)
self.myTableView.reloadData()
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: .Default, handler: nil)
alert.addTextFieldWithConfigurationHandler(nil)
alert.addAction(saveAction)
alert.addAction(cancelAction)
presentViewController(alert, animated: true, completion: nil)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return lists.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let myCell:UITableViewCell = myTableView.dequeueReusableCellWithIdentifier("Prototype1")!
let list = lists[indexPath.row]
print(lists[indexPath.row])
myCell.textLabel?.text = list.valueForKey("listTitle") as? String
return myCell
}
override func viewDidLoad() {
super.viewDidLoad()
self.myTableView.dataSource = self
self.myTableView.delegate = self
}
func saveItem(Saveitem: String)
{
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("List", inManagedObjectContext: managedContext)
let item = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext)
item.setValue(Saveitem, forKey: "listTitle")
do {
try managedContext.save()
lists.append(item)
}
catch {
print("Error")
}
}
}
As #Ismail says, you need to load the data you've been saving
Update your viewDidLoad function to look like this
override func viewDidLoad() {
super.viewDidLoad()
self.myTableView.dataSource = self
self.myTableView.delegate = self
// go get the data
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName:"List")
// you may need to sort the list
let sortDescriptor1 = NSSortDescriptor(key: "listTitle", ascending: true)
let sortDescriptors = [sortDescriptor1]
fetchRequest.sortDescriptors = sortDescriptors
var fetchedResults : [NSManagedObject] = []
do
{
fetchedResults = try managedContext.executeFetchRequest(fetchRequest) as! [NSManagedObject]
}
catch
{
return
}
for list in fetchedResults
{
lists.append(list)
}
self.myTableView.reloadData()
}
the data you get back will not always be in the order that you saved it, so it's worth thinking about adding a sort predicate
It does save you lists. your problem is you don't fetch the saved data in viewDidload or similar.
This code seems to be deleting the actual data ok however the table doesn't update without the row unless I force close the app and reopen.
Thanks in advance.
import UIKit
import CoreData
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
var lists = [NSManagedObject]()
var deleteListIndexPath: NSIndexPath? = nil
#IBOutlet weak var myTableView: UITableView!
#IBAction func addItem(sender: AnyObject) {
let alert = UIAlertController(title: "New List", message: "Add a new list", preferredStyle: .Alert)
let saveAction = UIAlertAction(title: "Save", style: .Default) { (UIAlertAction) -> Void in
let textField = alert.textFields![0] as UITextField
if textField != "" {
self.saveItem(textField.text!)
self.myTableView.reloadData()
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: .Default, handler: nil)
alert.addTextFieldWithConfigurationHandler(nil)
alert.addAction(saveAction)
alert.addAction(cancelAction)
presentViewController(alert, animated: true, completion: nil)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return lists.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let myCell:UITableViewCell = myTableView.dequeueReusableCellWithIdentifier("Prototype1")!
let list = lists[indexPath.row]
print(lists[indexPath.row])
myCell.textLabel?.text = list.valueForKey("listTitle") as? String
return myCell
}
override func viewDidLoad() {
super.viewDidLoad()
self.myTableView.dataSource = self
self.myTableView.delegate = self
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName:"List")
// you may need to sort the list
let sortDescriptor1 = NSSortDescriptor(key: "listTitle", ascending: true)
let sortDescriptors = [sortDescriptor1]
fetchRequest.sortDescriptors = sortDescriptors
var fetchedResults : [NSManagedObject] = []
do
{
fetchedResults = try managedContext.executeFetchRequest(fetchRequest) as! [NSManagedObject]
}
catch
{
return
}
for list in fetchedResults
{
lists.append(list)
}
self.myTableView.reloadData()
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if(editingStyle == .Delete ) {
// Find the LogItem object the user is trying to delete
let logItemToDelete = lists[indexPath.row]
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
managedContext.deleteObject(logItemToDelete)
self.myTableView.reloadData()
}
}
func saveItem(Saveitem: String)
{
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("List", inManagedObjectContext: managedContext)
let item = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext)
item.setValue(Saveitem, forKey: "listTitle")
do {
try managedContext.save()
lists.append(item)
}
catch {
print("Error")
}
}
}
You can use NSFetchedResultsController class with their NSFetchedResultsControllerDelegate protocol methods. And then you can update, delete, insert or move objects very easily!
If your tableView doesn't updated? You can use viewDidAppear function.
I think you still need to remove the "logItem" from the lists object.
lists.removeAtIndex(indexPath.row)
I could give you a more precise answer if you upload the code from this function at the tableview datasource protocol:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)