I want automatic updates on tableview..For that i have used NSFetchedResultsControlleras
lazy var fetchedResultsController: NSFetchedResultsController = {
// Initialize Fetch Request
let fetchRequest = NSFetchRequest(entityName: "Student")
// Add Sort Descriptors
let sortDescriptor = NSSortDescriptor(key: "grade", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
// Initialize Fetched Results Controller
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
// Configure Fetched Results Controller
fetchedResultsController.delegate = self
return fetchedResultsController
}()
But i have to filter the results after loading as of user selection as..
#IBAction func onSegmentValueChanged(sender: UISegmentedControl)
{
if sender.selectedSegmentIndex == 0{
//filter by grade
let fetchRequest = NSFetchRequest(entityName: "Student")
let sortDescriptor = NSSortDescriptor(key: "grade", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
let filterfetchResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
let predicate = NSPredicate(format: "address = %#","Russia")
filterfetchResultsController.fetchRequest.predicate = predicate
self.tableView.reloadData()
}else{
let fetchRequest = NSFetchRequest(entityName: "Student")
let sortDescriptor = NSSortDescriptor(key: "grade", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
let filterfetchResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
let predicate = NSPredicate(format: "grade = %d",10)
filterfetchResultsController.fetchRequest.predicate = predicate
self.tableView.reloadData()
}
}
This however reload the tableView but data is not filtered.how do i solve this problem?This is the demo project i am working on.Or should i use the normal way passing the results and reloading tableView as of normal way to solve this problem?
You must use self.fetchedResultsController, this is your datasource, not filterfetchResultsController: thereĀ“s no connection.
You must do a performFetch() to execute the changed predicates
This works for me:
#IBAction func onSegmentValueChanged(sender: UISegmentedControl)
{
if sender.selectedSegmentIndex == 1{
//filter by address
let predicate = NSPredicate(format: "address == %#","Russia")
self.fetchedResultsController.fetchRequest.predicate = predicate
}else{
let predicate = NSPredicate(format: "grade = %d",10)
self.fetchedResultsController.fetchRequest.predicate = predicate
}
do {
try self.fetchedResultsController.performFetch()
} catch {
let fetchError = error as NSError
print("\(fetchError), \(fetchError.userInfo)")
}
self.tableView.reloadData()
}
Related
I was using a lazy var in table view controller to get the data from CoreData. It was working good in swift2. But When I upgraded to Swift3, Its showing an error as below. Kindly help me to change for Swift3
Error : Cannot convert value of type 'Error' to specified type 'NSFetchedResultsController'
lazy var fetchedResultsController: NSfetchedResultsController =
{
let fetchRequest = NSFetchRequest(entityName: "EvtIvtTbl")
let sortDescriptor = NSSortDescriptor(key: "bym_kol", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
let fetchedResultsController = NSfetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: self.managedObjectContext,
sectionNameKeyPath: nil,
cacheName: nil)
fetchedResultsController.delegate = self
return fetchedResultsController
}()
In Swift 3.0, NSFetchedResultsController and NSFetchRequest want type parameters. Assuming that EvtIvtTbl is your NSManagedObject subclass, your code should look like this:
lazy var fetchedResultsController: NSFetchedResultsController<EvtIvtTbl> = {
let fetchRequest = NSFetchRequest<EvtIvtTbl>(entityName: "EvtIvtTbl")
let sortDescriptor = NSSortDescriptor(key: "bym_kol", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
let fetchedResultsController = NSFetchedResultsController<EvtIvtTbl>(fetchRequest: fetchRequest,
managedObjectContext: self.managedObjectContext,
sectionNameKeyPath: nil,
cacheName: nil)
fetchedResultsController.delegate = self
return fetchedResultsController
}()
how can I convert my NSFetchedResultsController to swift 3.0, i can't get it to work.... I tried apple's auto conversion but it's not working??
I had this:
lazy var fetchedResultsControler: NSFetchedResultsController = {
let fetchRequest = NSFetchRequest(entityName: "Mesages")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "timestamp", ascending: true)]
fetchRequest.predicate = NSPredicate(format: "user.id = %#", self.friend!.id!)
let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
frc.delegate = self
return frc
}()
automatically converted to this:
lazy var fetchedResultsControler: NSFetchedResultsController = { () -> <<error type>> in
let fetchRequest = NSFetchRequest(entityName: "Mesages")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "timestamp", ascending: true)]
fetchRequest.predicate = NSPredicate(format: "user.id = %#", self.friend!.id!)
let moc = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
frc.delegate = self
return frc
}()
but It's not working, it's asking me to put semi colons in random places
It is needed to set up NSFetchRequestResult inside brackets <>.
For swift 3.0:
lazy var fetchedResultsControler: NSFetchedResultsController<NSFetchRequestResult> = {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Mesages")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "timestamp", ascending: true)]
fetchRequest.predicate = NSPredicate(format: "user.id = %#", self.friend!.id!)
let moc = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
frc.delegate = self
return frc
}()
I want to load more cells when user in the last cell. I use CoreData and I get data from it. I use this answer to do what I want, but it didn't work. What problem can be there? Also I have one more question. I don't know why working only first implementation.
First implementation
var fetchedResultsController: NSFetchedResultsController {
let moc = DatabaseController.sharedInstance.managedObjectContext
let fetchRequest = NSFetchRequest()
let entity = NSEntityDescription.entityForName("Coctail", inManagedObjectContext: moc)
fetchRequest.entity = entity
fetchRequest.fetchLimit = 10
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: moc,
sectionNameKeyPath: nil,
cacheName: nil)
aFetchedResultsController.delegate = self
do {
try aFetchedResultsController.performFetch()
} catch {
fatalError("\(error)")
}
return aFetchedResultsController
}
Second Implementation
func initilizeFetchedResultsController() {
let moc = DatabaseController.sharedInstance.managedObjectContext
let fetchRequest = NSFetchRequest()
let entity = NSEntityDescription.entityForName("Coctail", inManagedObjectContext: moc)
fetchRequest.entity = entity
fetchRequest.fetchLimit = 10
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: moc,
sectionNameKeyPath: nil,
cacheName: nil)
aFetchedResultsController.delegate = self
do {
try aFetchedResultsController.performFetch()
} catch {
fatalError("\(error)")
}
fetchedResultsController = aFetchedResultsController
}
Hard to tell why the first solution but the second doesn't without seeing the other code that would have used the fetchedResultsController or called initilizeFetchedResultsController().
The reason you're not getting more data is that you've hardcoded your fetchLimit to 10. No matter what you do, you'll only ever get 10 results.
You'll need to change the fetchLimit to get more data. Check out this answer -- it is similar to what you'll need to do: https://stackoverflow.com/a/6786931/5605379
On compile this code:
func managedObjectContext_roster() -> NSManagedObjectContext {
return Messenger.sharedInstance.xmppRosterStorage!.mainThreadManagedObjectContext
}
I get the next error:
CoreData: error: Failed to call designated initializer on NSManagedObject class 'XMPPUserCoreDataStorageObject'
What this error means and how can I fix it? I searched in Google, but did not find anything
UPDATE
func fetchedResultsController() -> NSFetchedResultsController? {
if fetchedResultsControllerVar == nil {
let moc = MessengerRoster.sharedInstance.managedObjectContext_roster() as NSManagedObjectContext?
let entity = NSEntityDescription.entityForName("XMPPUserCoreDataStorageObject", inManagedObjectContext: moc!)
let sd1 = NSSortDescriptor(key: "sectionNum", ascending: true)
let sd2 = NSSortDescriptor(key: "displayName", ascending: true)
let sortDescriptors = [sd1, sd2]
let fetchRequest = NSFetchRequest()
fetchRequest.entity = entity
fetchRequest.sortDescriptors = sortDescriptors
fetchRequest.fetchBatchSize = 10
fetchedResultsControllerVar = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc!, sectionNameKeyPath: "sectionNum", cacheName: nil)
fetchedResultsControllerVar?.delegate = self
if fetchedResultsControllerVar?.performFetch(nil) == nil {
//Handle fetch error
}
}
return fetchedResultsControllerVar!
}
I am trying to filter core data objects depending on a date attribute.
This is my current code:
func getFetchedResultController(selectedEntity: NSString){
let appDelegate : AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedObjectContext: NSManagedObjectContext = appDelegate.managedObjectContext!
let fetchRequest = NSFetchRequest()
let entity = NSEntityDescription.entityForName(selectedEntity as String, inManagedObjectContext: managedObjectContext)
fetchRequest.entity = entity
fetchRequest.fetchBatchSize = 20
let date = NSDate()
let sectionSortDescriptor = NSSortDescriptor(key: "timeStamp < %#",date)
let sortDescriptors = [sectionSortDescriptor] //, secondSortDescriptor]
fetchRequest.sortDescriptors = sortDescriptors
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
aFetchedResultsController.delegate = self
self.fetchedResultsController = aFetchedResultsController
var error: NSError? = nil
if !self.fetchedResultsController.performFetch(&error) {
abort()
}
print(fetchedResultsController.fetchedObjects?.count ?? 0)
}
But I get an error at line:
let sectionSortDescriptor = NSSortDescriptor(key: "timeStamp < %#",date)
How should I change this sort descriptor to get the objects that have an older or a newer date on the "timeStamp" attribute?
Thank you.
To fetch all objects satisfying some condition you don't need a
sort descriptor but a predicate, for example:
let predicate = NSPredicate(format: "timeStamp < %#", date)
fetchRequest.predicate = predicate
You need a sort descriptor to get the objects in a specified order,
for example:
let sectionSortDescriptor = NSSortDescriptor(key: "timeStamp", ascending: true)
let sortDescriptors = [sectionSortDescriptor]
fetchRequest.sortDescriptors = sortDescriptors
Swift 3.0
This works with no problem for me
let fec:NSFetchRequest = YourEntity.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "type", ascending: true)
fec.sortDescriptors = [sortDescriptor]
let items = try! context.fetch(fec)
>Swift4
func getLastDateFromEntries(entityName:String) -> [NSManagedObject]{
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
let sortDescriptors = NSSortDescriptor(key: "dueDate", ascending: false) // dueDate is key
fetchRequest.sortDescriptors = [sortDescriptors]
fetchRequest.fetchLimit = 1 // add limit
let fetchedResults = try context.fetch(fetchRequest) as! [NSManagedObject]
return fetchedResults
}
catch {
print ("fetch task failed", error)
return []
}
}