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!
}
Related
I wanna use fetchedResultsController in my code with Swift3. I tried this way and other ways, but I can't make it. Here is my code(it doesn't work):
var fetchedResultsController: NSFetchedResultsController<Entity> {
let fetchRequest: NSFetchRequest<Entity>
if #available(iOS 10.0, *) {
fetchRequest = Entity.fetchRequest()
} else {
// Fallback on earlier versions
fetchRequest = NSFetchRequest(entityName: "Entity")
}
fetchRequest.fetchBatchSize = 20
let orderDescriptor = NSSortDescriptor(key: "archiveOrder", ascending: true)
let nameDesctiptor = NSSortDescriptor(key: "entityName", ascending: false)
fetchRequest.sortDescriptors = [orderDescriptor, nameDesctiptor]
let aFetchedResultsController: NSFetchedResultsController<Entity> = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: appDelegate.managedObjectContext, sectionNameKeyPath: nil, cacheName: "Master")
aFetchedResultsController.delegate = self
_fetchedResultsController = aFetchedResultsController
do {
try _FetchedResultsController.performFetch()
} catch {
let nserror = error as NSError
print("Unresolved error \(nserror), \(nserror.userInfo)")
}
return _FetchedResultsController!
}
Could you please give me any advice or suggestions?
Basically Apple recommends to declare NSFetchedResultsController as non-optional lazy initialized property using a closure which runs the code in the closure only once.
lazy var fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult> = { ... }()
Your code doesn't compile because Swift code is case sensitive that means _fetchedResultsController and _FetchedResultsController are two different things.
The rest of the code seems to be correct.
lazy var fetchedResultsController: NSFetchedResultsController<Entity> = {
let fetchRequest: NSFetchRequest<Entity>
if #available(iOS 10.0, *) {
fetchRequest = Entity.fetchRequest()
} else {
// Fallback on earlier versions
fetchRequest = NSFetchRequest(entityName: "Entity")
}
fetchRequest.fetchBatchSize = 20
let orderDescriptor = NSSortDescriptor(key: "archiveOrder", ascending: true)
let nameDesctiptor = NSSortDescriptor(key: "entityName", ascending: false)
fetchRequest.sortDescriptors = [orderDescriptor, nameDesctiptor]
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: appDelegate.managedObjectContext,
sectionNameKeyPath: nil,
cacheName: "Master")
aFetchedResultsController.delegate = self
do {
try aFetchedResultsController.performFetch()
} catch {
let nserror = error as NSError
print("Unresolved error \(nserror), \(nserror.userInfo)")
}
return aFetchedResultsController
}()
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 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()
}
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 []
}
}
I've managed to create my UICollectionViewController with swift, and implement the NSFetchedResultsController and fetch stuff from my CoreData model. All good there... But...
I can't seem to call any of the NSFetchedResultsControllerDelegate methods from within my extension. Code is as follows:
extension MainsViewController: NSFetchedResultsControllerDelegate {
func fetchedResultsController() -> NSFetchedResultsController {
// if(fetchedResultsController != nil){
// return fetchedResultsController()
// }
var fetchRequest = NSFetchRequest()
var context: NSManagedObjectContext = RKObjectManager.sharedManager().managedObjectStore.mainQueueManagedObjectContext
var entity = NSEntityDescription.entityForName("Dessert", inManagedObjectContext: context)
fetchRequest.entity = entity
fetchRequest.fetchBatchSize = 20
var sortDescriptor = NSSortDescriptor(key: "createdAt", ascending: false)
let sortDescriptors = [sortDescriptor]
fetchRequest.sortDescriptors = sortDescriptors
fetchedResultsController().delegate = self
var aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: "Master")
var error: NSError?
if !aFetchedResultsController.performFetch(&error){
println("An error:\(error) occured.")
}
return aFetchedResultsController
}
//Here is where i would call *#optional func controllerWillChangeContent(_ controller: NSFetchedResultsController!)* etc. etc.
}
But swift doesnt recognise theese methods. I can't figure out what it is I am missing.
Would be great if someone could help me out.
Thanks in advance
Chris
I think it should something like this:
var fetchedResultsController: NSFetchedResultsController {
get {
var fetchRequest = NSFetchRequest()
var context: NSManagedObjectContext = RKObjectManager.sharedManager().managedObjectStore.mainQueueManagedObjectContext
var entity = NSEntityDescription.entityForName("Dessert", inManagedObjectContext: context)
fetchRequest.entity = entity
fetchRequest.fetchBatchSize = 20
var sortDescriptor = NSSortDescriptor(key: "createdAt", ascending: false)
let sortDescriptors = [sortDescriptor]
fetchRequest.sortDescriptors = sortDescriptors
self.fetchedResultsController.delegate = self
var aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: "Master")
var error: NSError?
if !aFetchedResultsController.performFetch(&error){
println("An error:\(error) occured.")
}
return aFetchedResultsController
}
}
So your MainsViewController is a class, as I said in the comment above, so the first line has to look like this:
class MainsViewController: UIViewController, NSFetchedResultsControllerDelegate {
Unfortunatly I cannot test the code, but this can be understood like this: You have a property called fetchedResultsController and this will execute, when the fetchedResultsController is getting. So in the getter like you would do it in objective-c with a lazy getting method.
I found out that it was simply the auto complete feature that wasn't suggesting the method to me. Typing it out manually 'fixed' the issue. Sorry for wasting everybody's time...
Chris