Sorry guys if there's already a thread about it but been stuck with it for a while.
I'm kinda new to CoreData(knows only how to persist and fetch items only) and I'm trying to do a little query in my app which will load only the ones with the isDone attribute = to "True".
the thing is I don't know how to use NSFetchRequest & NSPredicate so im kinda stuck, hope you guys can help me out with some tips <3, Here's my code:
import Foundation
import CoreData
import UIKit
import SwipeCellKit
class TasksManViewController: UITableViewController, SwipeTableViewCellDelegate {
#IBOutlet weak var Sege: UISegmentedControl!
let isSwipeRightEnabled = true
var tasksArray = [Task](){
didSet {
// because we perform this operation on the main thread, it is safe
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
var doneTasksArr = [Task]() // an array of what to disply.
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
}
override func viewWillAppear(_ animated: Bool) {
loadTasks()
}
// MARK: - DataSource + Delegate Methods:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tasksArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "taskCellRow") as! SwipeTableViewCell
cell.delegate = self
cell.textLabel?.text = tasksArray[indexPath.row].title
return cell
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
if orientation == .left {
guard isSwipeRightEnabled else { return nil }
let doneAction = SwipeAction(style: .destructive, title: "Done") { (action, indexPath) in
//STEP1: Append the task to the doneTasksArr:
self.tasksArray[indexPath.row].isDone = true
self.doneTasksArr.append(self.tasksArray[indexPath.row])
//STEP2: Delete the task from the tasksArray since it was done.
self.context.delete(self.tasksArray[indexPath.row])
//STEP3: Remove the Row:
self.tasksArray.remove(at: indexPath.row)
//STEP4: Update the Model:
self.saveTasks()
self.tableView.reloadData()
}
//configure btn:
doneAction.backgroundColor = .cyan
return [doneAction]
} else {
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { action, indexPath in
self.context.delete(self.tasksArray[indexPath.row])
self.tasksArray.remove(at: indexPath.row)
self.saveTasks()
self.tableView.reloadData()
}
return [deleteAction]
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
// MARK: - Class Methods:
#IBAction func addBtnTapped(_ sender: UIBarButtonItem) {
insertNewTask()
}
func insertNewTask() {
var textField = UITextField()
let alert = UIAlertController(title: "New Task", message: "Please Add Your Task", preferredStyle: .alert)
alert.addTextField { (alertTextField) in
alertTextField.placeholder = "Create New Task"
textField = alertTextField
}
let action = UIAlertAction(title: "Add", style: .default) { (action) in
let newItem = Task(context: self.context)
newItem.title = textField.text!
newItem.isDone = false
self.tasksArray.append(newItem)
self.saveTasks()
self.tableView.reloadData()
}
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
}
// MARK: - Sege Section:
#IBAction func segeControlTapped(_ sender: UISegmentedControl) {
switch Sege.selectedSegmentIndex
{
case 0:
//Loading normal tasks which not done
loadTasks()
case 1:
//Loading the doneTasks:
loadDoneTasksFrom()
default:
print("There's something wrong with Sege!")
}
tableView.reloadData()
}
//MARK: - Model Manipulation Methods:
func saveTasks() {
do {
try! context.save()
} catch {
print("Error Saving context \(error)")
}
}
func loadTasks() {
let request: NSFetchRequest<Task> = Task.fetchRequest()
do{
tasksArray = try! context.fetch(request)
} catch {
print("There was an error with loading items \(error)")
}
}
func loadDoneTasksFrom() {
let request: NSFetchRequest<Task> = Task.fetchRequest()
request.predicate = NSPredicate(format: "isDone == %#", "true")
request.sortDescriptors = [NSSortDescriptor(key: "isDone", ascending: false)]
do{
tasksArray = try context.fetch(request)
} catch {
print("Error fetching data from context\(error)")
}
tableView.reloadData()
}
}
You can use one of these
NSPredicate(format: "isDone == %#", NSNumber(value: true))
NSPredicate(format: "isDone = %d", true)
You can write queries like this
static func getDoneTasks() -> NSFetchRequest<Task> {
let request:NSFetchRequest<Task> = Task.fetchRequest() as! NSFetchRequest<Task>
let sortDescriptor = NSSortDescriptor(key: "createdAt", ascending: false)
request.sortDescriptors = [sortDescriptor]
let isDone = true
request.predicate = NSPredicate(format: "isDone == %#", isDone)
return request
}
And then you just fetch them with:
#FetchRequest(fetchRequest: Task.getDoneTasks()) var doneTasks: FetchedResults<Task>
You also can add arguments etc. to your function and pass them in the FetchRequest
I can recommend this tutorial to understand the core concepts of coredata
Yay fellas! I solved it, I splited it to two functions like this: thank you very much for your help ! <3 I've learned how to use CoreData :) much love!.
func loadTasks() {
let request: NSFetchRequest<Task> = Task.fetchRequest()
request.predicate = NSPredicate(format: "isDone == %#", NSNumber(value: false))
request.sortDescriptors = [NSSortDescriptor(key: "isDone", ascending: false)]
do{
tasksArray = try! context.fetch(request)
} catch {
print("There was an error with loading items \(error)")
}
tableView.reloadData()
}
func loadDoneTasksFrom() {
let request:NSFetchRequest<Task> = Task.fetchRequest()
request.predicate = NSPredicate(format: "isDone == %#", NSNumber(value: true))
request.sortDescriptors = [NSSortDescriptor(key: "isDone", ascending: false)]
do{
tasksArray = try context.fetch(request)
} catch {
print("Error fetching data from context\(error)")
}
tableView.reloadData()
}
and then in the Sege for case 0(not done task) I loadTasks, and in case1 I load DoneTasks.
Related
This question already has answers here:
ActionSheet not working iPad
(8 answers)
Closed 3 years ago.
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 an 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 referred to the code in (How to Export Core Data to CSV in Swift 3?) to do the code for the exporting of coredata entries. My app is able to be built successfully. Adding and removing items from the tableview all work fine. It is only until I click on my export button that the app crashes.
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
}
}
It results in a "Thread 1: signal SIGABRT" error but I cannot find any typos in my code.
Here's the first call throw stack:
The full error code:
2019-06-26 10:04:33.843955+0800 TrueFalseAlarmV3[913:13287] libMobileGestalt MobileGestalt.c:890: MGIsDeviceOneOfType is not supported on this platform.
the app will now print: Engineer Name,Date of Alarm,Time of Alarm,True or False,Engineer Comments
2019-06-26 10:31:56.087370+0800 TrueFalseAlarmV3[913:13287] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /Users/danialaqil/Library/Developer/CoreSimulator/Devices/BF0A3A59-A660-4F1D-B0FE-F0D226479D8D/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
2019-06-26 10:31:56.087928+0800 TrueFalseAlarmV3[913:13287] [MC] Reading from private effective user settings.
2019-06-26 10:31:56.088526+0800 TrueFalseAlarmV3[913:18176] [MC] Filtering mail sheet accounts for bundle ID: imdadsl.TrueFalseAlarmV3, source account management: 1
2019-06-26 10:31:56.100398+0800 TrueFalseAlarmV3[913:18176] [MC] Filtering mail sheet accounts for bundle ID: imdadsl.TrueFalseAlarmV3, source account management: 2
2019-06-26 10:31:56.445312+0800 TrueFalseAlarmV3[913:13287] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIActivityViewController (). In its current trait environment, the modalPresentationStyle of a UIActivityViewController with this style is UIModalPresentationPopover. You must provide location information for this popover through the view controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the view controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.'
*** First throw call stack:
(
the throw call stack is in the image above
On iPad, UIActivityViewController needs to be presented in a popover or the app will crash, see this answer for details.
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
}
}
Did from the example: https://drive.google.com/open?id=0B3d4jY23eLOoejdRWkE0SG1VMkk
Step 1. I implemented the Core Data "Database". I have now 17 record and want to view all of them through the Cells in TableView ...
I did as like it was in tutorial, but it doesn't work. I wasted a week, and can't find an error :( It loads perfectly, but data is not displayed in cells :( So...
import Foundation
import CoreData
#available(iOS 10.0, *)
class DatabaseController
{
private init() { }
class func getContext() -> NSManagedObjectContext
{
return persistentContainer.viewContext
}
// MARK: - Core Data stack
static var persistentContainer: NSPersistentContainer =
{
let container = NSPersistentContainer.init(name: "Database")
//let container = NSPersistentContainer(name: "Database")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError?
{
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
class func saveContext ()
{
let context = persistentContainer.viewContext
if context.hasChanges
{
do {
try context.save()
}
catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
Mainly 3 files ... save/get/persistant container in "DatabaseController.swift"
Next "AppDelegate.Swift"...
func applicationWillTerminate(_ application: UIApplication)
{
DatabaseController.saveContext()
}
// MARK: - Core Data stack
lazy var applicationDocumentsDirectory: NSURL =
{
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return urls[urls.count-1] as NSURL
}()
lazy var managedObjectModel: NSManagedObjectModel =
{
let modelURL = Bundle.main.url(forResource: "Database", withExtension: "momd")!
return NSManagedObjectModel(contentsOf: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? =
{
var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.appendingPathComponent("Database.sqlite")
var error: NSError? = nil
var failureReason = "There was an error creating or loading the application's saved data."
do
{
try coordinator!.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
}
catch {
coordinator = nil
let dict = NSMutableDictionary()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error
let error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict as? [AnyHashable : Any])
NSLog("Unresolved error \(String(describing: error)), \(error.userInfo)")
print(error.localizedDescription)
abort()
}
return coordinator
}()
lazy var managedObjectContext: NSManagedObjectContext? =
{
let coordinator = self.persistentStoreCoordinator
if coordinator == nil
{
return nil
}
var managedObjectContext = NSManagedObjectContext()
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
Main functions responsible for DataCore
And final file for TableView. Before i made it as DataCore , cells were displayed like this
if indexPath.row == 0 {
cell.postImageView.image = UIImage(named: "ENTP")
cell.postTitleLabel.text = "ENTP"
cell.authorLabel.text = "Oleksandr Zheliezniak"
cell.authorImageView.image = UIImage(named: "author"):
} else if indexPath.row == 1 {
cell.postImageView.image = UIImage(named: "INTJ")
cell.postTitleLabel.text = "INTJ"
cell.authorLabel.text = "Gabriel Theodoropoulos"
cell.authorImageView.image = UIImage(named: "appcoda-300")
} else if indexPath.row == 2 {
cell.postImageView.image = UIImage(named: "ENTP")
cell.postTitleLabel.text = "ENTJ"
cell.authorLabel.text = "Gabriel Theodoropoulos"
cell.authorImageView.image = UIImage(named: "appcoda-300")
} else {
cell.postImageView.image = UIImage(named: "СеКс")
cell.postTitleLabel.text = "и виски"
cell.authorLabel.text = "Кокс Карибский))"
cell.authorImageView.image = UIImage(named: "appcoda-300")
}
Final file as below:
//
// PersonTableViewController.swift
//
// Created by Oleksandr Z 2017(c).
//
import UIKit
import Foundation
import CoreData
#available(iOS 10.0, *)
class PersonTableViewController: UITableViewController, NSFetchedResultsControllerDelegate
{
#IBAction func addButtonPressed(_ sender: Any)
{
switchScreen()
}
#IBOutlet weak var menuButton:UIBarButtonItem!
let moc: NSManagedObjectContext? = (UIApplication.shared.delegate as? AppDelegate)?.managedObjectContext
var fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult>?
var valueToPass:String!
//override var prefersStatusBarHidden: Bool {return true}
override func viewDidLoad()
{
super.viewDidLoad()
// MARK: - CORE DATA fetching out to the TableView
fetchedResultsController?.delegate = self
fetchedResultsController = NSFetchedResultsController(fetchRequest: IdentitiesFetchRequest(), managedObjectContext: self.moc!, sectionNameKeyPath: nil, cacheName: nil)
do
{
try fetchedResultsController?.performFetch()
}
catch let error as NSError
{
fatalError("Failed to initialize FetchedResultsController: \(error)")
}
//Visualization
if self.revealViewController() != nil
{
self.revealViewController().rearViewRevealWidth = 250
self.revealViewController().frontViewShadowRadius = 10
self.revealViewController().frontViewShadowColor = UIColor.black
self.revealViewController().frontViewShadowOpacity = 1
menuButton.target = self.revealViewController()
menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
self.clearsSelectionOnViewWillAppear = true
}
func IdentitiesFetchRequest() -> NSFetchRequest<NSFetchRequestResult>
{
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Identity")
let sortDescriptor = NSSortDescriptor(key: "lastModified", ascending: true)
fetchRequest.predicate = nil
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.fetchBatchSize = 20
fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc!, sectionNameKeyPath: nil, cacheName: nil)
fetchedResultsController?.delegate = self
do
{
try fetchedResultsController?.performFetch()
}
catch
{
fatalError("Failed to initialize FetchedResultsController: \(error)")
}
return fetchRequest
}
//MARK: NSFetchedResultsController Delegate Functions
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete { }
switch editingStyle
{
case .delete:
do
{
moc?.delete(fetchedResultsController?.object(at: indexPath) as! Identity)
try moc?.save()
}
catch
{
print(error)
}
case .insert:
break
case .none:
break
}
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?)
{
switch type
{
case NSFetchedResultsChangeType.insert:
tableView.insertRows(at: NSArray(object: newIndexPath!) as! [IndexPath], with: UITableViewRowAnimation.fade)
break
case NSFetchedResultsChangeType.delete:
tableView.deleteRows(at: NSArray(object: indexPath!) as! [IndexPath], with: UITableViewRowAnimation.fade)
break
case NSFetchedResultsChangeType.move:
tableView.deleteRows(at: NSArray(object: indexPath!) as! [IndexPath], with: UITableViewRowAnimation.fade)
tableView.insertRows(at: NSArray(object: newIndexPath!) as! [IndexPath], with: UITableViewRowAnimation.fade)
break
case NSFetchedResultsChangeType.update:
tableView.cellForRow(at: indexPath! as IndexPath)
break
//default:
// break
}
}
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
{
tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
{
tableView.endUpdates()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// Return the number of sections.
return fetchedResultsController?.sections?.count ?? 0
}
//Detailed viewCell
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
print("You selected cell #\(indexPath.row)!")
/*
// Get Cell Label
let indexPath = tableView.indexPathForSelectedRow!
let currentCell = tableView.cellForRow(at: indexPath)! as UITableViewCell
valueToPass = currentCell.textLabel?.text
performSegue(withIdentifier: "yourSegueIdentifer", sender: self)
*/
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if (segue.identifier == "ShowPerson")
{
//var viewController = segue.destination as! PersonDetailViewController
//viewController.passedValue = valueToPass
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return fetchedResultsController?.sections?[section].numberOfObjects ?? 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as!PersonTableViewCell
if let cellContact = fetchedResultsController?.object(at: indexPath) as? Identity
{
cell.textLabel?.text = "\(String(describing: cellContact.pName)), \(String(describing: cellContact.lastModified))"
}
let identityClassName:String = String(describing: Identity.self)
//let typeClassName:String = String(describing: Type.self)
let identity:Identity = NSEntityDescription.insertNewObject(forEntityName: identityClassName, into: DatabaseController.getContext()) as! Identity
//let type:Type = NSEntityDescription.insertNewObject(forEntityName: typeClassName, into: DatabaseController.getContext()) as! Type
let fetchRequest:NSFetchRequest<Identity> = Identity.fetchRequest()
do
{
let searchResults = try DatabaseController.getContext().fetch(fetchRequest)
print("number of results: \(searchResults.count)")
for result in searchResults as [Identity]
{
print("\(result.pName!) is \(result.accuracy)% Robesper. Updeted \(result.lastModified!).")
cell.postImageView.image = UIImage(named: "ENTP")
cell.postTitleLabel.text = identity.pName
cell.authorLabel.text = identity.imType
cell.authorImageView.image = UIImage(named: "author")
}
}
catch { print("Error: \(error)") }
return cell
}
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to toIndexPath: IndexPath) {
}
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return NO if you do not want the item to be re-orderable.
return true
}
func switchScreen()
{
let mainStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let vc : UIViewController = mainStoryboard.instantiateViewController(withIdentifier: "PersonDetail") as UIViewController
self.present(vc, animated: false, completion: nil)
}
}
Tried solution: Can't show the core data in tableview Swift but it didn't help. Tried all similar topics but can't solve the problem.
You seem to have two separate CoreData stacks: one set up by the DatabaseController class, which uses the viewContext from a NSPersistentContainer (introduced in iOS10), and another set up in the AppDelegate, which uses what looks like standard boilerplate from the older project templates. Your FRC uses the latter, whilst the rest of your code uses the former.
Although these seem to use the same model file, I suspect they are using different persistent stores. I think if you change this line:
fetchedResultsController = NSFetchedResultsController(fetchRequest: IdentitiesFetchRequest(), managedObjectContext: self.moc!, sectionNameKeyPath: nil, cacheName: nil)
to:
fetchedResultsController = NSFetchedResultsController(fetchRequest: IdentitiesFetchRequest(), managedObjectContext: DatabaseController.getContext(), sectionNameKeyPath: nil, cacheName: nil)
your FRC will be using the same context as the code that creates objects, so you should see some results. There are other problems with your code, so as Tom Harrington says in comments, you should learn how to use the debugger to iron them out.
var identities : [Identity] = []
override func viewDidLoad()
{
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
I tried a lot. There is no matter which solution to use (extensions,lazy,direct).
You should create two variables fore sure : ONE for all data array; SECOND for single data in array.
That is the way how it works basically:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as!PersonTableViewCell
let identity = identities[indexPath.row]
cell.postImageView.image = UIImage(named: <picture name>)
cell.postTitleLabel.text = identity.<Your attribute of entity>
cell.authorLabel.text = identity.<Your attribute of entity>
cell.authorImageView.image = UIImage(named: <picture name>)
return cell
}
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