How to fetch data from specific relationship entity in Swift? - ios

I have two relationship entities in Core Data. In the first entity I add names of companies in attribute. Then I move to second UIViewController and I add other attributes of specific company in the second entity which is relationship with the first entity. Also I have two UITableViewControllers, the first UITableViewController shows names of every company in cell. When I selected the specific company I move to the second UITableViewController. I want the second UITableViewController shows data of the specific company which I selected. I tried several different methods but I could not to make how I want. How can I make it?
The second UITableViewController code
override func viewDidLoad() {
super.viewDidLoad()
self.definesPresentationContext = true
println(currentCompany)
fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest(), managedObjectContext: managedObjectContext, sectionNameKeyPath: "activityCompany", cacheName: nil)
fetchedResultsController.delegate = self
fetchedResultsController.performFetch(nil)
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest(), managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - var and let
var currentCompany: String!
var managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext!
// MARK: - fetchResultsController
var fetchedResultsController: NSFetchedResultsController!
func fetchRequest() -> NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "Information")
var sortDescriptor = NSSortDescriptor(key: "company", ascending: true)
fetchRequest.fetchBatchSize = 50
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.predicate = NSPredicate(format: "company contains [c] %#", currentCompany)
return fetchRequest
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return fetchedResultsController.sections?.count ?? 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fetchedResultsController.sections?[section].numberOfObjects ?? 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
if var dataForCell = fetchedResultsController.objectAtIndexPath(indexPath) as? Information {
cell.textLabel?.text = dataForCell.activityCompany
cell.detailTextLabel?.text = dataForCell.foundedCompany
}
return cell
}
Entities
import Foundation
import CoreData
#objc(Company)
class Company: NSManagedObject {
#NSManaged var nameCompany: String
#NSManaged var information: NSSet
}
import Foundation
import CoreData
#objc(Information)
class Information: NSManagedObject {
#NSManaged var activityCompany: String
#NSManaged var foundedCompany: String
#NSManaged var company: Company
}
I save data into entites the following method.
// MARK: - #IBActions
#IBAction func saveData(sender: UIBarButtonItem) {
var companyEntity = NSEntityDescription.insertNewObjectForEntityForName("Company", inManagedObjectContext: managedObjectContext) as! NSManagedObject
var informationEntity = NSEntityDescription.insertNewObjectForEntityForName("Information", inManagedObjectContext: managedObjectContext) as! NSManagedObject
companyEntity.setValue(currentName, forKey: "nameCompany")
informationEntity.setValue(activityTextField.text, forKey: "activityCompany")
informationEntity.setValue(foundedTextField.text, forKey: "foundedCompany")
companyEntity.setValue(NSSet(object: informationEntity), forKey: "information")
var error: NSError?
managedObjectContext.save(&error)
var story = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
var naviController = story.instantiateViewControllerWithIdentifier("firstNavi") as! UINavigationController
presentViewController(naviController, animated: true, completion: nil)
}

I solved it.
func fetchRequest() -> NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "Information")
var sortDescriptor = NSSortDescriptor(key: "activityCompany", ascending: true)
fetchRequest.fetchBatchSize = 50
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.predicate = NSPredicate(format: "company.nameCompany contains [c] %#", currentCompany)
return fetchRequest
}

Related

How to fetch data from core data by Date as a section?

fetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: moc, sectionNameKeyPath:"time", cacheName: nil)
I am using this code where time is the column name that stores Date() object.
I want to get section base on Date
e.g..
29-11-2016 total row = 3
28-11-2016 total row = 1
but currently getting separate section for each time difference on
same date.
So, how can i achieve this using fetch request controller. ????
Thanks in advance.
This problem have already solution in stack overflow. It will work please check it.
import UIKit
import CoreData
class ExampleViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate {
#IBOutlet weak var tableView: UITableView!
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext!
var fetchedResultController: NSFetchedResultsController = NSFetchedResultsController()
var orders = [Order]()
var startDate : NSDate = NSDate()
var endDate : NSDate = NSDate()
override func viewDidLoad() {
super.viewDidLoad()
fetchedResultController.delegate = self
tableView.dataSource = self
tableView.delegate = self
fetchData()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return fetchedResultController.fetchedObjects!.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let order = fetchedResultController.fetchedObjects![section] as! Order
return ((order.products?.count ?? 0) + (order.services?.count ?? 0))
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let textCellIdentifier = "ExampleTableViewCell"
let row = indexPath.row
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! ExampleTableViewCell
let order = fetchedResultController.fetchedObjects![indexPath.section] as! Order // Data fetched using NSFetchedResultsController
let products = (order.products?.allObjects ?? [Product]()) as! [Product] // Swift Array
let services = (order.services?.allObjects ?? [Service]()) as! [Service] // Swift Array
if (row < products.count) { // this is a Product row
cell.orderLabel.text = products[row].name!
} else { // this is a Service row
cell.orderLabel.text = services[row-products.count].name!
}
return cell
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let order = fetchedResultController.fetchedObjects![section] as! Order
return "\(order.date)"
}
func orderFetchRequest() -> NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "Order")
let sortDescriptor = NSSortDescriptor(key: "date", ascending: true)
let predicate = NSPredicate(format: "date >= %# AND date <= %#", startDate, endDate) // startDate and endData are defined elsewhere
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.predicate = predicate
return fetchRequest
}
func fetchData() {
let fetchRequest = orderFetchRequest()
fetchedResultController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath:nil, cacheName: nil)
do {
try fetchedResultController.performFetch()
}
catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
}
I just copy and paste it. Hope it will work for you. If Not then i will help you.

How to make a simple fetch from relationship entities? Swift

I made two relationship entities in Xcode, I use the Swift. I made a simple relationship in Core Data.
Company's code
import Foundation
import CoreData
#objc(Company)
class Company: NSManagedObject {
#NSManaged var nameCompany: String
#NSManaged var additional: NSSet
}
The additional's code
import Foundation
import CoreData
#objc(Additional)
class Additional: NSManagedObject {
#NSManaged var acitvityCompany: String
#NSManaged var founded: String
#NSManaged var company: Company
}
I wrote a following code which adds data into entities. It works.
#IBAction func saveData(sender: UIBarButtonItem) {
var companyEntity = NSEntityDescription.insertNewObjectForEntityForName("Company", inManagedObjectContext: managedObjectContext) as! NSManagedObject
var additionalEntity = NSEntityDescription.insertNewObjectForEntityForName("Additional", inManagedObjectContext: managedObjectContext) as! NSManagedObject
companyEntity.setValue(nameCompanyTextField.text, forKey: "nameCompany")
additionalEntity.setValue(activityTextField.text, forKey: "acitvityCompany")
additionalEntity.setValue(foundedTextField.text, forKey: "founded")
companyEntity.setValue(NSSet(object: additionalEntity), forKey: "additional")
managedObjectContext.save(nil)
var storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
var navi = storyboard.instantiateViewControllerWithIdentifier("navi") as! UINavigationController
self.presentViewController(navi, animated: true, completion: nil)
// println("company \(companyEntity)")
// println("additional \(additionalEntity)")
}
When I move to UITableViewController which shows data from entities. If I fetch data from Additional entity I get an error. CoreData: FATAL ERROR: The persistent cache of section information does not match the current configuration. You have illegally mutated the NSFetchedResultsController's fetch request, its predicate, or its sort descriptor without either disabling caching or using +deleteCacheWithName:
If I fetch data only from Company entity it works good.
My UITableViewController
override func viewDidLoad() {
super.viewDidLoad()
self.definesPresentationContext = true
fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest(), managedObjectContext: managedObjectContext, sectionNameKeyPath: "nameCompany", cacheName: "nameCompany")
fetchedResultsController.delegate = self
fetchedResultsController.performFetch(nil)
fetchedResultsController2 = NSFetchedResultsController(fetchRequest: fetchRequest2(), managedObjectContext: managedObjectContext, sectionNameKeyPath: "company", cacheName: "company")
fetchedResultsController2.delegate = self
fetchedResultsController2.performFetch(nil)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.tableView.reloadData()
}
// MARK: - var and let
var managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext!
// MARK: - fetchedResultsController
var fetchedResultsController: NSFetchedResultsController!
var fetchedResultsController2: NSFetchedResultsController!
func fetchRequest() -> NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "Company")
let sortDescriptor = NSSortDescriptor(key: "nameCompany", ascending: true)
fetchRequest.fetchBatchSize = 50
fetchRequest.predicate = nil
fetchRequest.sortDescriptors = [sortDescriptor]
return fetchRequest
}
func fetchRequest2() -> NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "Additional")
let sortDescriptor = NSSortDescriptor(key: "company", ascending: true)
fetchRequest.fetchBatchSize = 50
fetchRequest.predicate = nil
fetchRequest.sortDescriptors = [sortDescriptor]
return fetchRequest
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return fetchedResultsController.sections?.count ?? 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fetchedResultsController.sections?[section].numberOfObjects ?? 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
if var dataForCell = fetchedResultsController.objectAtIndexPath(indexPath) as? Company {
var additionalCell = fetchedResultsController2.objectAtIndexPath(indexPath) as! Additional
cell.textLabel?.text = dataForCell.nameCompany
cell.detailTextLabel?.text = "\(additionalCell.acitvityCompany) - \(additionalCell.founded)"
}
return cell
}
I understood how to make it.
var currentDate: NSDate!
// MARK: - NSFetchedResultsController
var fetchedResultsController: NSFetchedResultsController!
func fetchRequest() -> NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "Car")
let sortDescriptor = NSSortDescriptor(key: "personCar", ascending: true)
fetchRequest.predicate = NSPredicate(format: "personRelationship.datePerson contains[c] %#", currentDate)
fetchRequest.fetchBatchSize = 50
fetchRequest.fetchLimit = 50
fetchRequest.sortDescriptors = [sortDescriptor]
println(fetchRequest)
return fetchRequest
}

CoreData - TableView does not get updated

So, I'm struggling to learn how to handle CoreData properly.
Here is my code:
import UIKit
import CoreData
class IngredientsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate {
let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var fetchedResultsController: NSFetchedResultsController?
override func viewDidLoad() {
super.viewDidLoad()
fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchIngredients(), managedObjectContext: moc!, sectionNameKeyPath: nil, cacheName: nil)
fetchedResultsController?.delegate = self
fetchedResultsController?.performFetch(nil)
}
func fetchIngredients() -> NSFetchRequest {
var fetchRequest = NSFetchRequest(entityName: "DetailsForRecipe")
let sortDescriptor = NSSortDescriptor(key: "ingredients", ascending: true)
fetchRequest.predicate = nil
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.fetchBatchSize = 20
return fetchRequest
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fetchedResultsController?.sections?[section].numberOfObjects ?? 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ingCell", forIndexPath: indexPath) as! UITableViewCell
if let ingCell = fetchedResultsController?.objectAtIndexPath(indexPath) as? DetailsForRecipe {
cell.textLabel?.text = ingCell.ingredients
}
return cell
}
}
and
import UIKit
import CoreData
class SingleIngredientViewController: UIViewController {
#IBOutlet var ingField: UITextField!
var moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func addIng(sender: AnyObject) {
let entityDescription = NSEntityDescription.entityForName("DetailsForRecipe", inManagedObjectContext: moc!)
let details = DetailsForRecipe(entity: entityDescription!, insertIntoManagedObjectContext: moc)
details.ingredients = ingField.text
var error: NSError?
moc?.save(&error)
if let err = error {
var status = err.localizedFailureReason
println(status)
} else {
println("Ingredient \(ingField.text) saved successfully!")
}
if let navigation = navigationController {
navigation.popViewControllerAnimated(true)
}
}
}
My model:
import Foundation
import CoreData
class DetailsForRecipe: NSManagedObject {
#NSManaged var name: String
#NSManaged var ingredients: String
#NSManaged var image: NSData
}
The app should insert the ingredient name in the text field, save it into coreData, then it should be retrieved in the table view. When I text the ingredient name and press "add", the prinln message says it was successfully saved, but the table view does not update.
What am I doing wrong here? I'm not a developer, I've read many tutorials on how to do this, but it is very confusing! So forgive me about this.
Thanks in advance!
I haven't read your full source code, but by doing an immediate glance, I don't see that you've called the tableview's reloadData function. If you don't have an IBOutlet set up for your table view, you will want to do that and then call reloadData() on it.
Call reloadData() on your table view after the change is made.

Storing with CoreData

my app is very simple: I have one tableview to store recipe *names and, for each recipe name, another tableview with several *ingredients for each recipe.
I already managed to save the name and the ingredients with CoreData, but here is the problem: when I press to add a NEW recipe name and enter the ingredients table view area, the ingredients saved for the previous recipe are there! How do I clear the table view to start a new one?
Also, my table views does not get updated immediately, I have to close the app and open it again. How do I fix it?
Note: If my question is too hard to understand, I can post some code! Thanks in advance, everyone =)
EDIT
code:
import UIKit
import CoreData
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate {
#IBOutlet var tableView: UITableView!
var imageList: [UIImage] = []
var moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var fetchedResultsController: NSFetchedResultsController?
override func viewDidLoad() {
fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchName(), managedObjectContext: moc!, sectionNameKeyPath: nil, cacheName: nil)
fetchedResultsController?.delegate = self
fetchedResultsController?.performFetch(nil)
tableView.reloadData()
}
func fetchName() -> NSFetchRequest {
var fetchRequest = NSFetchRequest(entityName: "Details")
let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
fetchRequest.predicate = nil
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.fetchBatchSize = 20
return fetchRequest
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fetchedResultsController?.sections?[section].numberOfObjects ?? 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("recipeCell", forIndexPath: indexPath) as! UITableViewCell
if let recipeCell = fetchedResultsController?.objectAtIndexPath(indexPath) as? Details {
cell.textLabel?.text = recipeCell.name
}
return cell
}
}
-
import UIKit
import CoreData
class InfoViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITableViewDelegate {
#IBOutlet var nameField: UITextField!
#IBOutlet var imageView: UIImageView!
var moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
override func viewDidLoad() {
super.viewDidLoad()
//Pick the image by tap
let tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "chooseImage:")
tapGestureRecognizer.numberOfTapsRequired = 1
imageView.addGestureRecognizer(tapGestureRecognizer)
imageView.userInteractionEnabled = true
}
//Pick the image by tapping, accessing the photoLibrary
func chooseImage(recognizer: UITapGestureRecognizer) {
let imagePicker: UIImagePickerController = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(imagePicker, animated: true, completion: nil)
}
//Put the selected image into the screen
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject:AnyObject]) {
let pickedImage: UIImage = (info as NSDictionary).objectForKey(UIImagePickerControllerOriginalImage) as! UIImage
// small picture
let smallPicture = scaleImageWith(pickedImage, newSize: CGSizeMake(288,148))
var sizeOfImageView:CGRect = imageView.frame
sizeOfImageView.size = smallPicture.size
imageView.frame = sizeOfImageView
imageView.image = smallPicture
picker.dismissViewControllerAnimated(true, completion: nil)
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
picker.dismissViewControllerAnimated(true, completion: nil)
}
func scaleImageWith(image:UIImage, newSize: CGSize) -> UIImage {
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
image.drawInRect(CGRectMake(0,0, newSize.width, newSize.height))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
#IBAction func addButton(sender: AnyObject) {
let entityDescription = NSEntityDescription.entityForName("Details", inManagedObjectContext: moc!)
let details = Details(entity: entityDescription!, insertIntoManagedObjectContext: moc)
details.name = nameField.text
var error: NSError?
moc?.save(&error)
if let err = error {
var status = err.localizedFailureReason
println("\(status)")
} else {
println("Ingredient \(nameField.text) saved successfully!")
}
if let navigation = navigationController {
navigation.popViewControllerAnimated(true)
}
}
}
-
import UIKit
import CoreData
class IngredientListViewController: UIViewController, NSFetchedResultsControllerDelegate {
#IBOutlet var tableView: UITableView!
var moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var fetchedResultsController: NSFetchedResultsController?
override func viewDidLoad() {
super.viewDidLoad()
fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchIngredient(), managedObjectContext: moc!, sectionNameKeyPath: nil, cacheName: nil)
fetchedResultsController?.delegate = self
fetchedResultsController?.performFetch(nil)
tableView.reloadData()
}
func fetchIngredient() -> NSFetchRequest {
var fetchRequest = NSFetchRequest(entityName: "Ingredients")
let sortDescriptor = NSSortDescriptor(key: "ingredients", ascending: true)
fetchRequest.predicate = nil
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.fetchBatchSize = 20
return fetchRequest
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fetchedResultsController?.sections?[section].numberOfObjects ?? 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ingCell", forIndexPath: indexPath) as! UITableViewCell
if let recipeCell = fetchedResultsController?.objectAtIndexPath(indexPath) as? Ingredients {
cell.textLabel?.text = recipeCell.ingredients
}
return cell
}
}
-
import UIKit
import CoreData
class IngredientViewController: UIViewController {
#IBOutlet var nameField: UITextField!
var moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func addButton(sender: AnyObject) {
let entityDescription = NSEntityDescription.entityForName("Ingredients", inManagedObjectContext: moc!)
let details = Ingredients(entity: entityDescription!, insertIntoManagedObjectContext: moc)
details.ingredients = nameField.text
var error: NSError?
moc?.save(&error)
if let err = error {
var status = err.localizedFailureReason
println("\(status)")
} else {
println("Ingredient \(nameField.text) saved successfully!")
}
if let navigation = navigationController {
navigation.popViewControllerAnimated(true)
}
}
}
and models:
import Foundation
import CoreData
class Ingredients: NSManagedObject {
#NSManaged var ingredients: String
#NSManaged var relationship: NSSet
}
import Foundation
import CoreData
class Details: NSManagedObject {
#NSManaged var name: String
#NSManaged var relationship: Ingredients
}
In outline:
You need to amend your model: currently each Details object can have only one Ingredients. I suspect you need this relationship to be "to many" so a recipe can have many ingredients.
You need to add a var (of type Details?) to your IngredientListViewController. This will represent the chosen Recipe. (eg. var chosenRecipe : Details?)
In fetchIngredient, you need to add a predicate to the fetch, to limit the results to the chosen recipe. eg. fetch.predicate = NSPredicate(format:"ANY relationship == %#", chosenRecipe)
Before segueing to this VC, you need to set the chosenRecipe (probably in prepareForSegue, or didSelectRowAtIndexPath in the preceding table view).
To get your TV to update automatically, use the fetchedResultsController delegate methods. (Have you implemented these?)

Adding sections, separated by dates, to UITableView in Swift CoreData

Can somebody tell me how to add sections with date using CoreData?
I have detailViewController which store all data from CoreDate, and AddTableViewController when we write some data.
Detail View Controller
import UIKit
import CoreData
class DetailViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate, AddTableViewControllerDelegate {
#IBOutlet weak var tableView: UITableView!
var detailTaskModel: Items!
var costsValues:Int!
#IBOutlet weak var sumLabel: UILabel!
// CoreData
let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext
var fetchedResultsController: NSFetchedResultsController = NSFetchedResultsController()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
fetchedResultsController = getFetchedResultsController()
fetchedResultsController.delegate = self
fetchedResultsController.performFetch(nil)
costsValues = getAccountCountSum()
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// UITableViewDataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fetchedResultsController.sections![section].numberOfObjects
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: DetailTableViewCell = tableView.dequeueReusableCellWithIdentifier("detailCell") as DetailTableViewCell
let thisCost = fetchedResultsController.objectAtIndexPath(indexPath) as Costs
cell.nazwaWydatkuLabel.text = thisCost.costsName
cell.wartośćLabel.text = "\(thisCost.costsValue) zł"
return cell
}
#IBAction func addCostButtonPressed(sender: UIBarButtonItem) {
self.performSegueWithIdentifier("addCostVC", sender: self)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return fetchedResultsController.sections!.count
}
override func viewDidAppear(animated: Bool) {
costsValues = getAccountCountSum()
refreshTable()
self.tableView.reloadData()
}
// CoreData Functions
func taskFetchRequest() -> NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "Costs")
let sortDescriptor = NSSortDescriptor(key: "costsDate", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
return fetchRequest
}
func getFetchedResultsController() -> NSFetchedResultsController {
fetchedResultsController = NSFetchedResultsController(fetchRequest: taskFetchRequest(), managedObjectContext: managedObjectContext!, sectionNameKeyPath: nil, cacheName: nil)
return fetchedResultsController
}
// NSFetchedResultsControllerDelegate
func controllerDidChangeContent(controller: NSFetchedResultsController) {
tableView.reloadData()
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
let thisCost = fetchedResultsController.objectAtIndexPath(indexPath) as Costs
managedObjectContext?.deleteObject(thisCost)
costsValues = getAccountCountSum()
refreshTable()
self.tableView.reloadData()
(UIApplication.sharedApplication().delegate as AppDelegate).saveContext()
}
// Sum count in all accouts
func getAccountCountSum() -> Int {
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let managedContext : NSManagedObjectContext = appDelegate.managedObjectContext!
var fetchRequest = NSFetchRequest(entityName: "Costs")
fetchRequest.returnsObjectsAsFaults = false
var results: NSArray = managedContext.executeFetchRequest(fetchRequest, error: nil)!
var accountsSum: Int = 0
for res in results {
var accountCount = res.valueForKey("costsValue") as Int
accountsSum += accountCount
}
self.sumLabel.text = String("\(costsValues) zł")
return accountsSum
}
func refreshTable() {
getAccountCountSum()
self.tableView.reloadData()
}
}
AddTableViewController
#IBAction func saveButtonTapped(sender: UIBarButtonItem) {
// CoreData Access
let appDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
var managedObjectContext = appDelegate.managedObjectContext
let entityDescription = NSEntityDescription.entityForName("Costs", inManagedObjectContext: managedObjectContext!)
let cost = Costs(entity: entityDescription!, insertIntoManagedObjectContext: managedObjectContext!)
cost.costsName = cellThreeNoteTextField.text
cost.costsValue = (cellOnePriceTextField.text).toInt()!
cost.costsDate = datePicker.date
// Saving data
appDelegate.saveContext()
var request = NSFetchRequest(entityName: "Costs")
var error:NSError? = nil
var results:NSArray = managedObjectContext!.executeFetchRequest(request, error: &error)!
for res in results {
println(res)
}
delegate?.refreshTable()
self.navigationController?.popViewControllerAnimated(true)
}
Since you're using an NSFetchedResultsController, you create sections by passing a key on your managed objects to the sectionNameKeyPath argument. The sections property of the fetched results controller will then break up the results into sections based on the values of that key path in the fetched objects.
You'll also need to implement UITableView callbacks to get it to use the sections-- for example, sectionIndexTitlesForTableView and tableView:titleForHeaderInSection:. These are described in the NSFetchedResultsController documentation.

Resources