Crash occurs when executing Share Extension twice in system Files to share file to app

与世无争的帅哥 提交于 2020-08-07 05:07:33

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!