2016-10-10 16 views
11

Tôi đang cố gắng sử dụng một fetchedResultsController để xử lý các kết quả trong UITable tôi.FetchedResultsController Swift 3 API Lạm dụng: Cố gắng để serialize cửa hàng truy cập vào phi sở hữu phối

Nó hoạt động ban đầu khi chương trình khởi động. Sau đó, khi tôi chuyển trở lại tab khoảng không quảng cáo nơi bảng của tôi là (đối với viewToAppear một lần nữa), đây là khi nó bị treo.

Tôi nhận được một lỗi crash runtime trong phương pháp của cửa sổ trong đó có bàn viewWillAppear() của tôi.

Cụ thể là nó treo trên tệp Inventory + CoredataProperties.swift trên dòng này let characters = name!.characters.map { String($0) }, nhưng tôi nghi ngờ lỗi là ở nơi khác vì điều này hoạt động ban đầu vậy tại sao không phải bây giờ trên lần tải lại thứ 2?

Đây là chức năng.

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 
    } 

Các lỗi xảy ra trên thử fetchedResultsController.performFetch() tuyên bố. Tôi nhận được rất nhiều lỗi trước khi vụ tai nạn xảy ra thực tế rằng "API Lạm dụng:. Cố gắng để serialize cửa hàng truy cập vào không sở hữu điều phối viên (PSC = 0x170265300, cửa hàng PSC = 0x0) Tôi đã refactoring mã của tôi để làm việc với 3 tiêu chuẩn nhanh chóng mới tôi có cảm giác tôi đã làm điều gì sai hoặc có thể một cái gì đó đã thay đổi với thế kết quả lấy công trình điều khiển.

Any help is appreciated như những gì có thể là nguyên nhân?

Nếu bạn nghĩ tôi đang thiếu một tập tin mà bạn cần để xem, chỉ cần cho tôi biết và tôi sẽ thêm nó vào mã nguồn có liên quan dưới đây.

CÓ THỂ NGUỒN LIÊN QUAN MÃ DƯỚI ĐÂY:

InventoryController.swift (Toàn bộ file)

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<Inventory> = { 
     return self.setFetchedResultsController() 
    }() 

    //Reference to search text for filtering 
    var m_searchText = "" 

    func setFetchedResultsController() -> NSFetchedResultsController<Inventory>{ 

     let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext 

     let inventoryFetchRequest : NSFetchRequest<Inventory> = 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) -> 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) -> 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 -> ViewDidLoad -> ... starting inits") 

//  // Do any additional setup after loading the view, typically from a nib. 
//  print("InventoryController -> ViewDidLoad -> ... starting inits") 
// 
     //First check to see if we have entities already. There MUST be entities, even if its DEMO data. 
     let inventoryFetchRequest = NSFetchRequest<Inventory>(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<=0){ 

       g_demoMode = true 
       print("No entities found for inventory. Demo mode = True. Creating default entities & 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 -> viewDidload -> ... 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 & 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) -> Int { 
//  //This scrolls to correct section based on title of what was pressed. 
//  return letterIndex.indexOf(title)! 
// } 

    func sectionIndexTitles(for tableView: UITableView) -> [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) -> Int { 

     if let sections = fetchedResultsController.sections { 
      let currentSection = sections[section] 
      return currentSection.numberOfObjects 
     } 

     return 0 
    } 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> 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) -> String? { 

     if let sections = fetchedResultsController.sections { 
      let currentSection = sections[section] 
      return currentSection.name 
     } 

     return nil 
    } 

    func numberOfSections(in tableView: UITableView) -> 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~ & 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<Int>) -> Int 
    { 
     var offset = 0 

     if range.lowerBound < 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 
    } 
} 

globals.swift

import Foundation 
import CoreData 

//Array of Inventory & Store Core Data Managed Objects 
var g_inventoryItems = [Inventory]() 
var g_storeList = [Store]() 
var g_appSettings = [AppSettings]() 
var g_demoMode = false 

Inventory + CoreDataProperties.swift

import Foundation 
import CoreData 

extension Inventory { 

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Inventory> { 
     return NSFetchRequest<Inventory>(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 000000ordering...(uses back number of barcode) 
    var numberendsection: String { 
     let characters = barcodeReverse!.characters.map { String($0) } 
     return (characters.first?.uppercased())! 
    } 

    //This is used for 0000000 ->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())! 
    } 

} 

Inventory.Swift

import Foundation 
import CoreData 


class Inventory: NSManagedObject { 

// Insert code here to add functionality to your managed object subclass 

} 

Ảnh chụp màn hình của lỗi

enter image description here

enter image description here

+0

Bất kỳ ai có ý tưởng hoặc điều gì tôi có thể thử? –

+0

NSFetchedResultsController đã thay đổi gần đây để tham chiếu Khoảng không quảng cáo nhưng vẫn là vấn đề tương tự. Ví dụ này, NSFetchedResultsController

+0

Tìm thấy một cái gì đó ở đây tôi sẽ cố gắng (https://forums.developer.apple.com/thread/60503). Nó đề cập đến việc lưu ngữ cảnh trước khi cố gắng tìm nạp. Tại thời điểm này tôi sẵn sàng thử bất cứ điều gì. –

Trả lời

4

Tôi đã xem xét tất cả các ý kiến ​​và nội dung của bạn được đăng ở đây. Bạn chưa chia sẻ một tệp nào ở đây, nhưng sự cố xảy ra bạn đang tạo các đối tượng được quản lý không hợp lệ trong ngữ cảnh.

Và sau đó bất cứ khi nào bạn gọi) chức năng (viewWillAppear trong InventoryViewController, nó tiết kiệm bối cảnh.

Cuối cùng, nó đồng bộ hóa các bản ghi trống vào cơ sở dữ liệu của bạn. Trong khi phân tích cú pháp các đối tượng không hợp lệ, nó đã cố gắng phân tích cú pháp giá trị nil, do đó bị lỗi.

Vui lòng không bao giờ đặt giá trị mặc định cho các đối tượng được quản lý mà bạn đang xác định là thuộc tính. Tôi hy vọng điều này sẽ làm rõ vấn đề của bạn.

+0

Awesome yeah đã giải quyết được vấn đề. Trong bảng vẽ ô nó đã tạo ra nó trong bối cảnh hơn và hơn nữa tạo ra các bản sao. Tất cả những gì tôi phải làm là tạo một tham chiếu tùy chọn bình thường cho nó mà không có ngữ cảnh. –

+0

Tôi vui vì nó đã giải quyết vấn đề của bạn một cách chính xác :) – softninja

1

Trong trường hợp điều này giúp bất kỳ ai bị lỗi "lạm dụng API: Cố gắng sắp xếp thứ tự lưu trữ truy cập trên điều phối viên không sở hữu" - tôi đã gặp lỗi vì tôi đã truy cập một đối tượng trong một đơn chưa bị phá hủy và vẫn sử dụng NSManagedObjectContext cũ sau khi tôi đặt lại NSPersistentStore và NSManagedObjectContext.

1

Tôi đã gặp sự cố tương tự và tôi đã chuyển sang api CoreData mới được giới thiệu trong ios10. Điều này sử dụng lớp NSPersistentContainer để tạo ngăn xếp và tạo các bối cảnh liên quan. Điều này giúp loại bỏ sự cần thiết phải tự lưu gọi hoặc đặt lệnh tạo bộ điều khiển kết quả tìm nạp.

Tốt bài đăng blog để đọc: https://useyourloaf.com/blog/easier-core-data-setup-with-persistent-containers/

thiết lập của tôi là một sau

tạo ra một cửa hàng NSPersistentContainer

let persistentContainer = NSPersistentContainer(name: "ModelFileName"); 

thiết lập cấu hình

let url = NSPersistentContainer.defaultDirectoryURL() 
let path = url.appendingPathComponent(persistentContainer.name); 
description.shouldAddStoreAsynchronously = true; //write to disk should happen on background thread 
self.persistentContainer.persistentStoreDescriptions = [description]; 

tải các cửa hàng

persistentContainer.loadPersistentStores(completionHandler: { (storeDescription, error) in 
     if let error = error { 
       fatalError("Unresolved error \(error), \(error.localizedDescription)") 
     } 

    //configure context for main view to automatically merge changes 
    persistentContainer.viewContext.automaticallyMergesChangesFromParent = true; 
}); 

trong bộ điều khiển xem bạn có thể truy cập vào bối cảnh xem bằng cách gọi

persistentContainer.viewContext 

nếu bạn cần phải thực hiện những thay đổi bạn có thể gọi

persistentContainer.performBackgroundTask({ (context) in ... }); 

hoặc bạn có thể nhận được một bối cảnh nền

let context = persistentContainer.newBackgroundContext() 
context.perform({ ... }) 
Các vấn đề liên quan