问题
The app uses Share Extension to import a string of .txt files to Core Data. And then syncs the Core Data to iCloud. There is an entity called Item
. When sharing a new item in system Files through Share Extension, the code needs to calculate the order
for the new item to be imported. And the code is:
import Foundation
import CoreData
@objc(Item)
public class Item: NSManagedObject, Identifiable {
class func nextOrder() -> Int {
let keyPathExpression = NSExpression.init(forKeyPath: "order")
let maxNumberExpression = NSExpression.init(forFunction: "max:", arguments: [keyPathExpression])
let expressionDescription = NSExpressionDescription()
expressionDescription.name = "maxNumber"
expressionDescription.expression = maxNumberExpression
expressionDescription.expressionResultType = .decimalAttributeType
var expressionDescriptions = [AnyObject]()
expressionDescriptions.append(expressionDescription)
// Build out our fetch request the usual way
let request: NSFetchRequest<NSFetchRequestResult> = Item.fetchRequest()
request.resultType = .dictionaryResultType
request.propertiesToFetch = expressionDescriptions
request.predicate = nil
// Our result should to be an array of dictionaries.
var results: [[String:AnyObject]]?
do {
results = try CoreData.stack.context.fetch(request) as? [[String:NSNumber]] <-- errors here, Exception: "executeFetchRequest:error: <null> is not a valid NSFetchRequest."
if let maxNumber = results?.first!["maxNumber"] {
// Return one more than the current max order
return maxNumber.intValue + 1
} else {
// If no items present, return 0
return 0
}
} catch _ {
// If any failure, just return default
return 0
}
}
}
The code of Share Extension is:
import UIKit
import Social
import CoreServices
import CoreData
class ShareViewController: SLComposeServiceViewController {
var item = [Item]()
var newItem: Item?
override func isContentValid() -> Bool {
return true
}
override func didSelectPost() {
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
if let inputItem = extensionContext!.inputItems.first as? NSExtensionItem {
if let itemProvider = inputItem.attachments?.first {
// This line was missing
if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeText as String) {
itemProvider.loadItem(forTypeIdentifier: kUTTypeText as String) { (urlItem, error) in
if let filePathURL = urlItem as? URL {
do {
let nextOrder = Item.nextOrder() <-- errors here, Exception: "executeFetchRequest:error: <null> is not a valid NSFetchRequest."
// Some operation to import new item
// useless code for this question
// ...
} catch {
print("error")
}
}
}
}
}
}
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
lazy var persistentContainer: NSPersistentCloudKitContainer = {
let container = NSPersistentCloudKitContainer(name: "iCloud.com.xxxxx")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
The Share Extension works well in the first time sharing. After the sharing, a new item is added in the Core Data.
But it will crash when sharing files the second time, saying Exception: "executeFetchRequest:error: <null> is not a valid NSFetchRequest."
The code errors is in the func nextOrder()
, and the line is results = try CoreData.stack.context.fetch(request) as? [[String:NSNumber]]
which has been commented in the code above.
A similar question is here. But is my bug the same as it? And I did not solve it following the answers in the question.
来源:https://stackoverflow.com/questions/62860449/crash-occurs-when-executing-share-extension-twice-in-system-files-to-share-file