What this CoreData error means? - ios

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

Using fetchedResultsController with swift3

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
}()

convert syntax to swift 3.0 NSFetchedResultsController

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
}()

filter NSFetchedResultsController result swift 2

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()
}

Core Data sort descriptor with NSDate, iOS with Swift

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 []
}
}

Trouble calling NSFetchedResultsControllerDelegate methods

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

Resources