我在应用程序中执行两个核心数据任务时遇到问题。本质上,我从URL连接中引入数据,然后将该信息保存到Core Data中。不过,在执行此操作之前,请确保已拥有新数据,然后删除核心数据中的当前内容(实质上是覆盖现有数据)。
我尝试使用异步和同步块,甚至尝试使用wait()函数来减慢速度,还有很多其他事情,但是我仍然遇到并发错误。谁能帮忙吗?非常感谢你!
这是我的视图已加载:
override func viewDidLoad() {
super.viewDidLoad()
//Setup app delegate to pass to sale function
let thisAppDelegate = UIApplication.shared.delegate as! AppDelegate
//update sale information if possible
self.getJSONFromURLAndSaveToCoreData(appDelegate: thisAppDelegate)
}
这是实际功能:
//this function is fetching the JSON from URL
func getJSONFromURLAndSaveToCoreData(appDelegate : AppDelegate){
//create a NSURL
let url = NSURL(string: urlString)
//fetch the data from the url
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
//If the retrieved information is a JSON Object, and can be treated as an NSArray...
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSArray {
//iterate through the object. For each item...
for item in jsonObj! {
//setup array variables
var rangeArray: [RangeObject] = []
var contractArray: [ContractObject] = []
//Parse all items
if let itemObject = item as? NSObject {
//Identify ranges
let newRanges = itemObject.value(forKey: "ranges") as! NSArray
//for each item in ranges...
for item in newRanges {
//Create range objects
if let itemObject = item as? NSObject{
let start = Int(itemObject.value(forKey: "start") as! String)!
let end = Int(itemObject.value(forKey: "end") as! String)!
let thisRange = RangeObject(startValue: start, endValue: end)
//add to range array
rangeArray.append(thisRange)
}
}
//Identify contracts
let newContracts = itemObject.value(forKey: "contract") as! NSArray
//for each item in contracts...
for item in newContracts {
//Create contract objects
if let itemObject = item as? NSObject{
let newUomName = itemObject.value(forKey: "uom_name") as! String
let newHaulerID = Int(itemObject.value(forKey: "hauler_id") as! String)!
let newExpirationDate = itemObject.value(forKey: "expiration_date") as! String
let newSaleProductName = itemObject.value(forKey: "sale_product_name") as! String
let newHaulerName = itemObject.value(forKey: "hauler_name") as! String
let newDestinationName = itemObject.value(forKey: "destination_name") as! String
let newSaleProductID = Int(itemObject.value(forKey: "sale_product_id") as! String)!
let thisContract = ContractObject(uomName: newUomName, haulerID: newHaulerID, expirationDate: newExpirationDate, saleProductName: newSaleProductName, haulerName: newHaulerName, destinationName: newDestinationName, saleProductID: newSaleProductID)
//add to contract array
contractArray.append(thisContract)
}
}
//Set all other values to variables
let newTimberSaleName = itemObject.value(forKey: "timber_sale_name") as! String
let newTimberSaleID = Int(itemObject.value(forKey: "timber_sale_id") as! String)!
let newOperatorName = itemObject.value(forKey: "lb_operator_name") as! String
let newOperatorID = itemObject.value(forKey: "lb_operator_id") as! String
let newGeneralID = itemObject.value(forKey: "id") as! Int
//Use all of the variables and arrays to create a new Sale object
let newSaleObject = SaleObject(ranges: rangeArray, timberSaleName: newTimberSaleName, lbOperatorName: newOperatorName, lbOperatorID: newOperatorID, timberSaleID: newTimberSaleID, ID: newGeneralID, contracts: contractArray)
//Add the object to saleArray
self.saleArray.append(newSaleObject)
}
}
}
//TODO: This is where completion stuff goes
//If data was pulled from the internet, delete current data.
if self.saleArray.count != 0 {
// Setup ManagedObjectContext
let thisManagedContext =
appDelegate.persistentContainer.viewContext
// Setup fetch request with information
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "Sale")
//Attempt to fetch the information
do {
let sales = try thisManagedContext.fetch(fetchRequest)
//for each object in sales...
for object in sales {
//delete the object
thisManagedContext.delete(object)
}
print("Deleted!")
} catch let error {
print("Delete all data error :", error)
}
}//End Delete
//Save to Core Data
//Create link to ManagedObject
var sales: [NSManagedObject] = []
// Setup ManagedObjectContext
let currentManagedContext = appDelegate.persistentContainer.viewContext
//For each sale...
for item in self.saleArray {
// Identify the sale entity information
let saleEntity =
NSEntityDescription.entity(forEntityName: "Sale",
in: currentManagedContext)!
//setup a managed object to manage that entity
let sale = NSManagedObject(entity: saleEntity,
insertInto: currentManagedContext)
// Set all the values of the entity
sale.setValue(item.timberSaleName, forKeyPath: "timberSaleName")
sale.setValue(item.timberSaleID, forKeyPath: "timberSaleID")
sale.setValue(item.lbOperatorName, forKeyPath: "lbOperatorName")
sale.setValue(item.lbOperatorID, forKeyPath: "lbOperatorID")
sale.setValue(item.ID, forKeyPath: "id")
sale.setValue(item.ranges, forKeyPath: "ranges")
sale.setValue(item.contracts, forKeyPath: "contracts")
// Try to save the sale
do {
try currentManagedContext.save()
sales.append(sale)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
}).resume()
}
这是错误:
Serious application error. Exception was caught during Core Data
change processing. This is usually a bug within an observer of
NSManagedObjectContextObjectsDidChangeNotification. -[__NSCFSet
addObject:]: attempt to insert nil with userInfo (null)
CoreData: error: Serious application error. Exception was caught
during Core Data change processing. This is usually a bug within an
observer of NSManagedObjectContextObjectsDidChangeNotification. -
[__NSCFSet addObject:]: attempt to insert nil with userInfo (null)
2018-12-10 15:16:45.076035-0600 ACTIVITY[4608:3386565] ***
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[__NSCFSet addObject:]:
attempt to insert nil'
*** First throw call stack:
(
0 CoreFoundation 0x000000010ccc91bb
__exceptionPreprocess + 331
1 libobjc.A.dylib 0x000000010b83f735
objc_exception_throw + 48
2 CoreFoundation 0x000000010ccc9015 + .
[NSException raise:format:] + 197
3 CoreFoundation 0x000000010cca48da -
[__NSCFSet addObject:] + 202
4 CoreData 0x000000010c63bb2b -
[NSManagedObjectContext(_NSInternalChangeProcessing)
_processPendingUpdates:] + 379
5 CoreData 0x000000010c63632b -
[NSManagedObjectContext(_NSInternalChangeProcessing)
_processRecentChanges:] + 1163
6 CoreData 0x000000010c63a0a0 -
[NSManagedObjectContext save:] + 416
7 Load BOSS 0x000000010ae5552b
$S9ACTIVITY18MainViewControllerC31getJSONFromURLAndSaveToCoreData
11appDelegateyAA03AppN0C_tFy10Foundation0L0VSg_So13NSURL .
ResponseCSgs5Error_pSgtcfU_ + 19531
8 ACTIVITY 0x000000010ae55dfa
$S9ACTIVITY18MainViewControllerC31getJSONFromURLAndSaveTo
CoreData11appDelegateyAA03AppN0C_tFy10Foundation0L0VSg_
So13NSURLResponseCSgs5Error_pSgtcfU_TA + 26
9 ACTIVITY 0x000000010ae55f60
$S10Foundation4DataVSgSo13NSURLResponseCSgs5Error
_pSgIegggg_So6NSDataCSgAGSo7NSErrorCSgIeyByyy_TR + 336
10 CFNetwork 0x000000010e29f940 __75-
[__NSURLSessionLocal
taskForClass:request:uploadFile:bodyData:completion:]_block_invoke +
19
11 CFNetwork 0x000000010e2b5b0c __49-
[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke + 172
12 Foundation 0x000000010b2acf9e
__NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
13 Foundation 0x000000010b2acea5 -
[NSBlockOperation main] + 68
14 Foundation 0x000000010b2a9c14 -
[__NSOperationInternal _start:] + 689
15 Foundation 0x000000010b2afc4b
__NSOQSchedule_f + 227
16 libdispatch.dylib 0x000000010f274595
_dispatch_call_block_and_release + 12
17 libdispatch.dylib 0x000000010f275602
_dispatch_client_callout + 8
18 libdispatch.dylib 0x000000010f27854d
_dispatch_continuation_pop + 565
19 libdispatch.dylib 0x000000010f277927
_dispatch_async_redirect_invoke + 859
20 libdispatch.dylib 0x000000010f28600a
_dispatch_root_queue_drain + 351
21 libdispatch.dylib 0x000000010f2869af
_dispatch_worker_thread2 + 130
22 libsystem_pthread.dylib 0x000000010f66470e
_pthread_wqthread + 619
23 libsystem_pthread.dylib 0x000000010f664435
start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type
NSException
这是我的核心数据模型:
顺便说一句,该错误不是永久性的。看来是随机发生的。