在系统文件中执行共享扩展两次以将文件共享到应用程序时发生崩溃

gar*_*ong 5 core-data ios icloud swift ios8-share-extension

该应用程序使用 Share Extension 将一串 .txt 文件导入 Core Data。然后将核心数据同步到 iCloud。有一个实体叫做Item。通过 Share Extension 在系统 Files 中共享新项目时,代码需要计算order要导入的新项目的 。代码是:

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Share Extension的代码是:

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)")
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

共享扩展在第一次共享时效果很好。共享后,核心数据中添加了一个新项目。

但是第二次共享文件时会崩溃,说 Exception: "executeFetchRequest:error: <null> is not a valid NSFetchRequest."

代码错误在func nextOrder(), 行是results = try CoreData.stack.context.fetch(request) as? [[String:NSNumber]]在上面的代码中注释的。

一个类似的问题是here。但是我的错误和它一样吗?我没有按照问题中的答案解决它。