title: FetchedResultsController Swift 3 API Misuse: Attempt to serialize store access on non-owning coordinator
body: <p>I'm attempting to use a fetchedResultsController to handle the results in my UITable.</p>
  
  <p>It works initially when the program starts up.  Then when I switch back to the inventory tab where my table is (for the viewToAppear again), this is when it crashes.</p>
  
  <p>I'm getting a runtime crash error in my viewWillAppear() method of the window which has the table.</p>
  
  <p>In particular it crashes on the Inventory+CoredataProperties.swift file on this line <code>let characters = name!.characters.map { String($0) }</code>, but I suspect the error is somewhere else as this works initially so why not now on the 2nd reload?</p>
  
  <p>Here is the function.</p>
  
  <pre><code>override func viewWillAppear(_ animated: Bool) {
          print("view appearing")
          //When the view appears its important that the table is updated.
  
          //Trigger Event on SearchBar in case returning from BarCode Scanner
  //        self.searchBar:SearchBar textDidChange:recentlySearchedWord;
          //searchBar.performSelector(":textDidChange")
  
          //Perform another fetch again to get correct data~
          do {
              //fetchedResultsController. //this will force setter code to run again.
              print("attempting fetch again, reset to use lazy init")
              fetchedResultsController = setFetchedResultsController() //sets it again so its correct.
  
              try fetchedResultsController.performFetch()
          } catch {
              print("An error occurred")
          }
  
  
          inventoryTable.reloadData()//this is important to update correctly for changes that might have been made
      }
  </code></pre>
  
  <p>The error occurs on the <strong>try fetchedResultsController.performFetch()</strong> statement.  I'm getting a lot of errors before the actual crash occurs saying <strong>"API Misuse: Attempt to serialize store access on non-owning coordinator (PSC = 0x170265300, store PSC = 0x0)</strong>.  I've been refactoring my code to work with the new swift 3 standards I have a feeling I did something wrong or maybe something changed with how the fetched results controller works.</p>
  
  <p>Any help is appreciated as to what could be the cause?</p>
  
  <p><strong>If you think I'm missing a file you need to see, just let me know and I'll add it to the relevant source code below.</strong></p>
  
  <p>POSSIBLE RELEVANT SOURCE CODE BELOW:</p>
  
  <p><strong>InventoryController.swift (Entire File)</strong></p>
  
  <pre><code>import UIKit
  import CoreData
  import Foundation
  
  class InventoryController: UIViewController, UISearchBarDelegate, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate {
      @available(iOS 2.0, *)
  
      //Create fetchedResultsController to handle Inventory Core Data Operations
      lazy var fetchedResultsController: NSFetchedResultsController&lt;Inventory&gt; = {
          return self.setFetchedResultsController()
      }()
  
      //Reference to search text for filtering
      var m_searchText = ""
  
      func setFetchedResultsController() -&gt; NSFetchedResultsController&lt;Inventory&gt;{
  
          let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
  
          let inventoryFetchRequest : NSFetchRequest&lt;Inventory&gt; = Inventory.fetchRequest()
  
          var primarySortDescriptor = NSSortDescriptor(key: "name", ascending: true)//by default assume name.
  
          print("primarySortDescriptor...")
  
          if(g_appSettings[0].indextype=="numberfront"){
              primarySortDescriptor = NSSortDescriptor(key: "barcode", ascending: true)
          }else if(g_appSettings[0].indextype=="numberback"){
              primarySortDescriptor = NSSortDescriptor(key: "barcodeReverse", ascending: true)
          }else if(g_appSettings[0].indextype=="numberfourth"){
              primarySortDescriptor = NSSortDescriptor(key: "barcodeFourth", ascending: true, selector: #selector(NSString.localizedCompare(_:)))
          }
  
           print("set primarySortDescriptor")
  
          //let secondarySortDescriptor = NSSortDescriptor(key: "barcode", ascending: true)
  
          inventoryFetchRequest.sortDescriptors = [primarySortDescriptor]
  
          print("set sort descriptors to fetch request")
  
          var storefilter : Store? = nil
          var predicate: NSPredicate
  
          //Store should never be set to nil, the first store should always be selected by default.  For fringe cases just in case ... support added so doesn't break
          if(g_appSettings[0].selectedStore != nil){
  
              storefilter = g_appSettings[0].selectedStore
              predicate = NSPredicate(format: "store = %@", storefilter!) //default predicate assuming store is selected
  
              //However if search text is present then modify predicate
              if(m_searchText != ""){
                  predicate = NSPredicate(format: "store = %@ AND name contains[cd] %@ OR store = %@ AND barcode contains[cd] %@", storefilter!,m_searchText,storefilter!,m_searchText)
  
              }
              //This will ensure correct data relating to store is showing (and if any filters present, them as well)
  
              inventoryFetchRequest.predicate = predicate
          }else{
              if(m_searchText != ""){
                  predicate = NSPredicate(format: "name contains[cd] %@ OR barcode contains[cd] %@",m_searchText,m_searchText)
                  inventoryFetchRequest.predicate = predicate
                  //This will ensure correct data relating to store is showing
              }
          }
  
          //default assume letter section
          var frc = NSFetchedResultsController(
              fetchRequest: inventoryFetchRequest,
              managedObjectContext: moc,
              sectionNameKeyPath: "lettersection",
              cacheName: nil)
  
          if(g_appSettings[0].indextype=="numberfront"){
              frc = NSFetchedResultsController(
                  fetchRequest: inventoryFetchRequest,
                  managedObjectContext: moc,
                  sectionNameKeyPath: "numbersection",
                  cacheName: nil)
          }else if(g_appSettings[0].indextype=="numberback"){
              frc = NSFetchedResultsController(
                  fetchRequest: inventoryFetchRequest,
                  managedObjectContext: moc,
                  sectionNameKeyPath: "numberendsection",
                  cacheName: nil)
          }else if(g_appSettings[0].indextype=="numberfourth"){
              frc = NSFetchedResultsController(
                  fetchRequest: inventoryFetchRequest,
                  managedObjectContext: moc,
                  sectionNameKeyPath: "numberfourthsection",
                  cacheName: nil)
          }
  
  
          print("set the frc")
  
          frc.delegate = self
  
          return frc
      }
  
      @IBOutlet weak var searchBar: UISearchBar!
      @IBOutlet weak var inventoryTable: UITableView!
  
      // Start DEMO Related Code
      var numberIndex = ["0","1","2","3","4","5","6","7","8","9"]
      var letterIndex = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
  
      var previousNumber = -1 //used so we show A,A, B,B, C,C etc for proper testing of sections
  
      func createInventoryDummyData(number: Int) -&gt; Inventory{
          let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
  
          let tempInventory = NSEntityDescription.insertNewObject(forEntityName: "Inventory", into: moc) as! Inventory
          if(number-1 == previousNumber){
              tempInventory.name = "\(letterIndex[number-2])-Test Item # \(number)"
              previousNumber = -1//reset it again
          }else{
              tempInventory.name = "\(letterIndex[number-1])-Test Item # \(number)"
              previousNumber = number //set previous letter accordingly
          }
          tempInventory.barcode = "00000\(number+1)00\(number)"
  
          //special exception to demo barcode reader
          if(number==5){
              tempInventory.barcode = "0051111407592"
          }
  
          if(number==6){
              tempInventory.barcode = "0036000291452"
          }
  
          tempInventory.barcodeReverse = String(tempInventory.barcode!.characters.reversed())
  
          //Convert barcode into array of characters and take note if its size for indexing
          let bcArraySize = Int(tempInventory.barcode!.characters.count) - 1//for correct indexing
          var bcArray = tempInventory.barcode!.characters.map { String($0) }
  
          print(bcArray)
          print(bcArraySize)
  
          //Take the digits from the 4th one at a time and convert to strings concatenating as you go.
          let fourth = "\(bcArray[bcArraySize-3])"+"\(bcArray[bcArraySize-2])"+"\(bcArray[bcArraySize-1])"+"\(bcArray[bcArraySize])"
  
          print(fourth)
  
          //Finally convert that into a number again and set to barcodeFourth
          tempInventory.barcodeFourth = fourth
  
          print(tempInventory.barcodeFourth!)
  
          //tempInventory.barcodeFourth =
          //print(tempInventory.barcodeReverse)
  
  
          tempInventory.currentCount = 0
          tempInventory.id = number as NSNumber?
          tempInventory.imageLargePath = "http://distribution.tech//uploads/inventory/7d3fe5bfad38a3545e80c73c1453e380.png"
          tempInventory.imageSmallPath = "http://distribution.tech//uploads/inventory/7d3fe5bfad38a3545e80c73c1453e380.png"
          tempInventory.addCount = 0
          tempInventory.negativeCount = 0
          tempInventory.newCount = 0
          tempInventory.store_id = 1 //belongs to same store for now
  
          //Select a random store to belong to 0 through 2 since array starts at 0
          let lo = 0;
          let hi = 2;
          let aRandomInt = Int.random(range:lo...hi)
          tempInventory.setValue(g_storeList[aRandomInt], forKey: "store") //assigns inventory to one of the stores we created.
  
          return tempInventory
      }
  
      func createStoreDummyData(number:Int) -&gt; Store{
          let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
  
          let tempStore = NSEntityDescription.insertNewObject(forEntityName: "Store", into: moc) as! Store
  
          tempStore.address = "100\(number) lane, Miami, FL"
          tempStore.email = "store\(number)@centraltire.com"
          tempStore.id = number as NSNumber?
          tempStore.lat = 1.00000007
          tempStore.lng = 1.00000008
          tempStore.name = "Store #\(number)"
          tempStore.phone = "123000000\(number)"
  
          return tempStore
      }
  
      // End DEMO Related Code
  
      override func viewDidLoad() {
          super.viewDidLoad()
  
          let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
  
          print("InventoryController -&gt; ViewDidLoad -&gt; ... starting inits")
  
  //        // Do any additional setup after loading the view, typically from a nib.
  //        print("InventoryController -&gt; ViewDidLoad -&gt; ... starting inits")
  //
          //First check to see if we have entities already.  There MUST be entities, even if its DEMO data.
          let inventoryFetchRequest = NSFetchRequest&lt;Inventory&gt;(entityName: "Inventory")
          //let storeFetchRequest = NSFetchRequest(entityName: "Store")
  
          do {
              let inventoryRecords = try moc.fetch(inventoryFetchRequest)
              //Maybe sort descriptor here? But how to organize into sectioned array?
  
              if(inventoryRecords.count&lt;=0){
  
                  g_demoMode = true
                  print("No entities found for inventory.  Demo mode = True.  Creating default entities &amp; store...")
  
                  //Reset the Stores
                  g_storeList = [Store]()
  
                  var store : Store //define variable as Store type
  
                  for index in 1...3 {
                      store = createStoreDummyData(number: index)
                      g_storeList.append(store)
                  }
  
                  //save changes for inventory we added
                  do {
                      try moc.save()
                      print("saved to entity")
                  }catch{
                      fatalError("Failure to save context: \(error)")
                  }
  
                  var entity : Inventory //define variable as Inventory type
  
                  for index in 1...52 {
                      let indexFloat = Float(index/2)+1
                      let realIndex = Int(round(indexFloat))
                      entity = createInventoryDummyData(number: realIndex)
                      g_inventoryItems.append(entity)
                  }
  
                  //Save the changes
                  (UIApplication.shared.delegate as! AppDelegate).saveContext()
  
                  print("finished creating entities")
              }
  
          }catch{
              fatalError("bad things happened \(error)")
          }
  
  
  
  
  //        //perform fetch we need to do.
  //        do {
  //            try fetchedResultsController.performFetch()
  //        } catch {
  //            print("An error occurred")
  //        }
  
          print("InventoryController -&gt; viewDidload -&gt; ... finished inits!")
      }
  
      override func viewWillAppear(_ animated: Bool) {
          print("view appearing")
          //When the view appears its important that the table is updated.
  
          //Trigger Event on SearchBar in case returning from BarCode Scanner
  //        self.searchBar:SearchBar textDidChange:recentlySearchedWord;
          //searchBar.performSelector(":textDidChange")
  
          //Perform another fetch again to get correct data~
          do {
              //fetchedResultsController. //this will force setter code to run again.
              print("attempting fetch again, reset to use lazy init")
              fetchedResultsController = setFetchedResultsController() //sets it again so its correct.
  
              try fetchedResultsController.performFetch()
          } catch {
              print("An error occurred")
          }
  
  
          inventoryTable.reloadData()//this is important to update correctly for changes that might have been made
      }
  
      // MARK: - Navigation
  
      // In a storyboard-based application, you will often want to do a little preparation before navigation
      override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
          // Get the new view controller using segue.destinationViewController.
          // Pass the selected object to the new view controller.
          print("inventoryItemControllerPrepareForSegueCalled")
  
          if segue.identifier == "inventoryInfoSegue" {
              let vc = segue.destination as! InventoryItemController
              vc.hidesBottomBarWhenPushed = true //hide the tab bar.  This prevents crashing error from being on this page then syncing &amp; returning.
              if let cell = sender as? InventoryTableViewCell{
                  vc.inventoryItem = cell.inventoryItem //sets the inventory item accordingly, passing its reference along.
              }else{
                  print("sender was something else")
              }
          }
  
      }
  
  //    func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -&gt; Int {
  //        //This scrolls to correct section based on title of what was pressed.
  //        return letterIndex.indexOf(title)!
  //    }
  
      func sectionIndexTitles(for tableView: UITableView) -&gt; [String]? {
          //This is smart and takes the first letter of known sections to create the Index Titles
          return self.fetchedResultsController.sectionIndexTitles
      }
  
      func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
  
          if let sections = fetchedResultsController.sections {
              let currentSection = sections[section]
              return currentSection.numberOfObjects
          }
  
          return 0
      }
  
      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {
          let cell = tableView.dequeueReusableCell(withIdentifier: "InventoryTableCell", for: indexPath as IndexPath) as! InventoryTableViewCell
  
          print("IndexPath=")
          print(indexPath)
  
          let inventory : Inventory = fetchedResultsController.object(at: indexPath as IndexPath)
          cell.inventoryItem = inventory
  
          cell.drawCell() //uses passed inventoryItem to draw it's self accordingly.
  
          return cell
      }
  
  
      func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -&gt; String? {
  
          if let sections = fetchedResultsController.sections {
              let currentSection = sections[section]
              return currentSection.name
          }
  
          return nil
      }
  
      func numberOfSections(in tableView: UITableView) -&gt; Int {
          if let sections = fetchedResultsController.sections {
              return sections.count
          }
  
          return 0
      }
  
      func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
          //dispatch_async(dispatch_get_main_queue()) {
          //[unowned self] in
          print("didSelectRowAtIndexPath")//does not recognize first time pressed item for some reason?
          let selectedCell = self.tableView(tableView, cellForRowAt: indexPath) as? InventoryTableViewCell
  
          self.performSegue(withIdentifier: "inventoryInfoSegue", sender: selectedCell)
          //}
      }
  
  
      @IBAction func BarcodeScanBarItemAction(sender: UIBarButtonItem) {
          print("test of baritem")
      }
      @IBAction func SetStoreBarItemAction(sender: UIBarButtonItem) {
          print("change store interface")
      }
  
      func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
          self.barcodeTextDidChange(searchText: searchText)
      }
  
      func barcodeTextDidChange(searchText: String){
          print("text is changing")
          //Code to change NSFetchRequest Here~ &amp; Reload Table
  
          m_searchText = searchText //sets the local variable to this class so the setFetchedResultsController() will update accordingly
  
          //Perform another fetch again to get correct data~
          do {
              //fetchedResultsController. //this will force setter code to run again.
              print("attempting fetch again, reset to use lazy init")
              fetchedResultsController = setFetchedResultsController() //sets it again so its correct.
              try fetchedResultsController.performFetch()
          } catch {
              print("An error occurred")
          }
  
          inventoryTable.reloadData()//refreshes the data~
  
      }
  
      func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
          print("ended by cancel")
          searchBar.text = ""
  
          m_searchText = "" //set the search text accordingly back to nothing.
  
          //Perform another fetch again to get correct data~
          do {
              //fetchedResultsController. //this will force setter code to run again.
              print("attempting fetch again, reset to use lazy init")
              fetchedResultsController = setFetchedResultsController() //sets it again so its correct.
  
              try fetchedResultsController.performFetch()
          } catch {
              print("An error occurred")
          }
  
          inventoryTable.reloadData()//refreshes the data~
  
          searchBar.resignFirstResponder()
      }
  
      func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
          print("ended by search")
          searchBar.resignFirstResponder()
      }
  
      func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
          print("ended by end editing")
          searchBar.resignFirstResponder()
      }
  
      func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
          print("DidBeginEditing")
          //searchBar.keyboardType = UIKeyboardType.NamePhonePad
      }
  
  
      @IBAction func unwindBackToInventory(segue: UIStoryboardSegue) {
          print("unwind attempt")
  
          let barcode = (segue.source as? ScannerViewController)?.barcode
          searchBar.text = barcode!
  
          barcodeTextDidChange(searchText: searchBar.text!)//force it to re-run function manually.
  
          print("barcode="+barcode!)
  
          inventoryTable.reloadData()//reload the data to be safe.
  
      }
  
  }
  
  //Extention to INT to create random number in range.
  extension Int
  {
      static func random(range: ClosedRange&lt;Int&gt; ) -&gt; Int
      {
          var offset = 0
  
          if range.lowerBound &lt; 0   // allow negative ranges
          {
              offset = abs(range.lowerBound)
          }
  
          let mini = UInt32(range.lowerBound + offset)
          let maxi = UInt32(range.upperBound   + offset)
  
          return Int(mini + arc4random_uniform(maxi - mini)) - offset
      }
  }
  </code></pre>
  
  <p><strong>globals.swift</strong></p>
  
  <pre><code>import Foundation
  import CoreData
  
  //Array of Inventory &amp; Store Core Data Managed Objects
  var g_inventoryItems = [Inventory]()
  var g_storeList = [Store]()
  var g_appSettings = [AppSettings]()
  var g_demoMode = false
  </code></pre>
  
  <p><strong>Inventory+CoreDataProperties.swift</strong></p>
  
  <pre><code>import Foundation
  import CoreData
  
  extension Inventory {
  
      @nonobjc public class func fetchRequest() -&gt; NSFetchRequest&lt;Inventory&gt; {
          return NSFetchRequest&lt;Inventory&gt;(entityName: "Inventory");
      }
  
      @NSManaged var addCount: NSNumber?
      @NSManaged var barcode: String?
      @NSManaged var barcodeReverse: String?
      @NSManaged var barcodeFourth: String?
      @NSManaged var currentCount: NSNumber?
      @NSManaged var id: NSNumber?
      @NSManaged var imageLargePath: String?
      @NSManaged var imageSmallPath: String?
      @NSManaged var name: String?
      @NSManaged var negativeCount: NSNumber?
      @NSManaged var newCount: NSNumber?
      @NSManaged var store_id: NSNumber?
      @NSManaged var store: Store?
  
      //This is used for A,B,C ordering...
      var lettersection: String {
          let characters = name!.characters.map { String($0) }
          return (characters.first?.uppercased())!
      }
  
      //This is used for 1,2,3 ordering... (using front of barcode and using barcodeReverse)
      var numbersection: String {
          let characters = barcode!.characters.map { String($0) }
          return (characters.first?.uppercased())!
      }
  
      //This is used for 0000000123 ordering...(uses back number of barcode)
      var numberendsection: String {
          let characters = barcodeReverse!.characters.map { String($0) }
          return (characters.first?.uppercased())!
      }
  
      //This is used for 0000000 -&gt; 0123 ordering...(uses back 4th number of barcode)
      var numberfourthsection: String {
          let characters = barcodeFourth!.characters.map { String($0) }
          //print("characters")
          //print(characters)
          return (characters.first?.uppercased())!
      }
  
  }
  </code></pre>
  
  <p><strong>Inventory.Swift</strong></p>
  
  <pre><code>import Foundation
  import CoreData
  
  
  class Inventory: NSManagedObject {
  
  // Insert code here to add functionality to your managed object subclass
  
  }
  </code></pre>
  
  <p><strong>Screenshots of Errors</strong></p>
  
  <p><a href="https://i.stack.imgur.com/8waBL.png" rel="noreferrer"><img src="https://i.stack.imgur.com/8waBL.png" alt="enter image description here"></a></p>
  
  <p><a href="https://i.stack.imgur.com/AOFjj.png" rel="noreferrer"><img src="https://i.stack.imgur.com/AOFjj.png" alt="enter image description here"></a></p>