Using fetchedResultsController with swift3 - ios

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

Related

Ios Swift3 : lazy var fetchrequestcontroller showing an error

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

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

How to initialize a NSFetchedResultsController in iOS 10 Swift 3

I can't get my NSFetchedResultsController initialized in iOS 10 using Swift 3 within CoreDataTableViewController from AECoreDataUI.
let request = NSFetchRequest<NasaPicture>(entityName:"NasaPicture")
request.predicate = Predicate(format: "isPagedResult == YES")
request.sortDescriptors = [SortDescriptor(key: "date", ascending: false)]
fetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
Compiler is complaining that
"Cannot convert value of type NSFetchedResultsController<NasaPicture> to expected type NSFetchedResultsController<_>"
The controller is now using generic type for swift, but it is not inferring the entity type correctly. I've tried explicitly:
fetchedResultsController = NSFetchedResultsController<NasaPicture>(fetchRequest: request, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
No luck either.
Thanks!
NSFetchRequest is now a generic. NSFetchedResultsController is a generic too. Therefore, when declaring variables, you have to use a generic declaration, e.g.:
var fetchedResultsController: NSFetchedResultsController<NasaPicture>?
when we need to declare variable, then we have to use a generic declaration
please check below code for NSFetchedResultsController in swift 3..
override func viewDidLoad() {
super.viewDidLoad()
do {
try self.fetchedResultsController.performFetch()
} catch {
let fetchError = error as NSError
print("Unable to Perform Fetch Request")
print("\(fetchError), \(fetchError.localizedDescription)")
}
}
// MARK: - NSFetchedResultsController
fileprivate lazy var fetchedResultsController: NSFetchedResultsController<UserExistenceOnXMPPCD> = {
let fetchRequest = NSFetchRequest<UserExistenceOnXMPPCD>(entityName: "UserExistenceOnXMPPCD")
fetchRequest.sortDescriptors = [
NSSortDescriptor(key: "name", ascending: true)]
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext:CoreDataController.sharedInstance.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
try! fetchedResultsController.performFetch()
fetchedResultsController.delegate = self
if let quotes = fetchedResultsController.fetchedObjects {
if quotes.count > 0 {
print(quotes.count)
}
}
return fetchedResultsController
}()
// MARK: - NSFetchedResultsController delegate methods
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.reloadData()
}
Simply call the function:
private func setupFetchedResultsController() {
let context = NSManagedObjectContext.mr_default()
let fetchRequest = NSFetchRequest<Month>(entityName: "Month")
let dateDescriptor = NSSortDescriptor(key: "date", ascending: false)
fetchRequest.sortDescriptors = [dateDescriptor]
fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: "year", cacheName: nil)
fetchedResultsController.delegate = self
try! fetchedResultsController.performFetch()
tableView.reloadData()
}

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

What this CoreData error means?

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!
}

Resources