configurePersistentStoreCoordinator not called for saveAs NSPersistentDocument

后端 未结 4 1488
醉梦人生
醉梦人生 2021-01-21 11:18

I experience an odd behaviour regarding saving an NSPersistentDocument. I can create a new document which is autosaved without an issue. But when I save it write(to: ofTyp

4条回答
  •  伪装坚强ぢ
    2021-01-21 11:44

    Another, simpler workaround:

    The following code has a bug. Please refer to the bug fixed version cited below.

    extension NSPersistentStoreCoordinator {
    
      @objc func x_migratePersistentStore(_ store: NSPersistentStore, to URL: URL, options: [AnyHashable : Any]? = nil, withType storeType: String) throws -> NSPersistentStore {
        var opt: [AnyHashable : Any] = options ?? [:]
    
        if #available(OSX 10.13, *) {
          opt[NSBinaryStoreSecureDecodingClasses] = NSSet(array: [ NSColor.self ])
        }
    
        return try x_migratePersistentStore(store, to: URL, options: opt, withType: storeType)
      }
    
    }
    
    class Document: NSPersistentDocument {
    
      override init() {
        super.init()
    
        let s1 = #selector(NSPersistentStoreCoordinator.migratePersistentStore(_:to:options:withType:))
        let s2 = #selector(NSPersistentStoreCoordinator.x_migratePersistentStore(_:to:options:withType:))
        let m1 = class_getInstanceMethod(NSPersistentStoreCoordinator.self, s1)!
        let m2 = class_getInstanceMethod(NSPersistentStoreCoordinator.self, s2)!
        method_exchangeImplementations(m1, m2)
      }
    
      override func configurePersistentStoreCoordinator(for url: URL, ofType fileType: String, modelConfiguration configuration: String?, storeOptions: [String : Any]? = nil) throws {
        // keep yours
      }
    
    }
    

    Added:

    This workaround is going to be a practical solution until they enhance NSPersistentDocument.write(to...) to take into account of options or they implement other means to handle options. Those options will be given to NSPersistentStoreCoordinator.migratePersistentStore(...) and then be used to instantiate NSPersistentStore.

    Bug Fixed Version:

    There was a bug in the preceding workaround. Opening document files, creating new files, making changes, waiting for thirty second to the document being auto-saved, closing them, and/or save-as-ing them randomly would cause the initial error. Reported by Wizard of Kneup.

    Here is a fixed version using singleton to make sure swizzling is applied only once.

    extension NSPersistentStoreCoordinator {
    
      @objc func x_migratePersistentStore(_ store: NSPersistentStore, to URL: URL, options: [AnyHashable : Any]? = nil, withType storeType: String) throws -> NSPersistentStore {
        var opt: [AnyHashable : Any] = options ?? [:]
    
        if #available(OSX 10.13, *) {
          opt[NSBinaryStoreSecureDecodingClasses] = NSSet(array: [ NSColor.self ])
        }
    
        return try x_migratePersistentStore(store, to: URL, options: opt, withType: storeType)
      }
    
      class MigratePersistentStoreInitializer {
        init() {
          let s1 = #selector(NSPersistentStoreCoordinator.migratePersistentStore(_:to:options:withType:))
          let s2 = #selector(NSPersistentStoreCoordinator.x_migratePersistentStore(_:to:options:withType:))
          let m1 = class_getInstanceMethod(NSPersistentStoreCoordinator.self, s1)!
          let m2 = class_getInstanceMethod(NSPersistentStoreCoordinator.self, s2)!
          method_exchangeImplementations(m1, m2)
        }
    
        static let singlton = MigratePersistentStoreInitializer()  // Lazy Stored Property
      }
    
    }
    
    class Document: NSPersistentDocument {
    
      override init() {
        super.init()
        let _ = NSPersistentStoreCoordinator.MigratePersistentStoreInitializer.singlton
      }
    
      override func configurePersistentStoreCoordinator(for url: URL, ofType fileType: String, modelConfiguration configuration: String?, storeOptions: [String : Any]? = nil) throws {
        // keep yours
      }
    
    }
    

    References:

    • Lazy Stored Properties

提交回复
热议问题