¿Cómo utilizar ManagedObjectModel de Core Data dentro de un marco?

Estoy intentando migrar una parte específica de una de mis aplicaciones a un marco para poder usarla en mi propia aplicación y en uno de esos widgets nuevos de iOS 8. Esta parte es la que maneja todos mis datos en Core Data. Es bastante sencillo moverlo todo y acceder a él. Solo tengo problemas para acceder a mi file momd allí.

Al crear el NSManagedObjectModel todavía bash cargar el momd como se ilustra en las templates de código de Apple:

 NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyApp" withExtension:@"momd"]; __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 

Desafortunadamente, modelURL permanece nil y, por lo tanto, MyApp bloquea al acceder a la stack de datos centrales con este error:

 2014-08-01 22:39:56.885 MyApp[81375:7417914] Cannot create an NSPersistentStoreCoordinator with a nil model 2014-08-01 22:39:56.903 MyApp[81375:7417914] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot create an NSPersistentStoreCoordinator with a nil model' 

Entonces, ¿cuál es la forma correcta de hacerlo cuando se trabaja dentro de un marco con Core Data?

Debe arrastrar el file xcdatamodeld y soltarlo en las Fases de compilation | Comstackr orígenes para los objectives que utilizan el marco. Luego, cuando el destino se ejecuta, su [NSBundle mainBundle] contendrá el model (file momd).

Llegué un poco tarde para el problema de flohei, pero espero que esto ayude a cualquier persona que pase por allí. ¡Es posible hacer que esto funcione sin tener que ejecutar script-fu para copyr resources!

Por defecto, la plantilla Core Data de Apple te ofrece algo como esto:

 lazy var managedObjectModel: NSManagedObjectModel = { let modelURL = NSBundle.mainBundle().URLForResource("MyCuteCoreDataModel", withExtension: "momd")! return NSManagedObjectModel(contentsOfURL: modelURL)! }() 

Eso cargaría sus resources de Core Data fuera del package principal. La key aquí es: si el model de datos principales se carga en un marco, el file .momd está en el package de ese marco . Entonces, en cambio, hacemos esto:

 lazy var managedObjectModel: NSManagedObjectModel = { let sexyFrameworkBundleIdentifier = "com.heybaby.xxx" let customKitBundle = NSBundle(identifier: sexyFrameworkBundleIdentifier)! let modelURL = customKitBundle.URLForResource("MyCuteCoreDataModel", withExtension: "momd")! return NSManagedObjectModel(contentsOfURL: modelURL)! }() 

Eso debería hacerlo funcionar.

Crédito: https://www.andrewcbancroft.com/2015/08/25/sharing-a-core-data-model-with-a-swift-framework/

Puede que llegue un poco tarde para contestar esto, pero esto es lo que resolvió mi problema:

Con mi framework también estoy ofreciendo un package con resources como imágenes y otras cosas. Poner el file xcdatamodeld allí no dio nada, ya que este file se está creando con el proyecto y, como resultado, obtienes una carpeta momd en tu package de aplicaciones (que en realidad no se encuentra en nuestro caso). He creado otro objective, no un marco, pero la aplicación, la creó y copió el momd desde su package de aplicaciones a mi package por separado en el proyecto (el que va con el marco). Después de hacer esto, solo necesita cambiar la url de resources del package principal al nuevo:

 // ... NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"separate_bundle" ofType:@"bundle"]; NSURL *modelURL = [[NSBundle bundleWithPath:bundlePath] URLForResource:@"your_model" withExtension:@"momd"]; // ... 

Funcionó bien para mí. De lo único que estoy al tanto es App Store Review, que aún no conocía. Entonces, si has encontrado una solución mejor, comparte.

EDITAR

Encontramos mejor solución. Puedes build el model tú mismo. De Core Data Programming Guide :

Un model de datos es un recurso de implementación. Además de los detalles de las entidades y las properties en el model, un model que usted crea en Xcode contiene información sobre el diagtwig: su layout, los colors de los elementos, etc. Esta última información no es necesaria en time de ejecución. El file model se comstack utilizando el comstackdor model, momc, para eliminar la información extraña y hacer que la carga en time de ejecución del recurso sea lo más eficiente posible. Un directory "fuente" xcdatamodeld se comstack en un directory de deployment momd, y un file "fuente" xcdatamodel se comstack en un file de deployment madre.

momc se encuentra en / Developer / usr / bin /. Si desea utilizarlo en sus propios scripts de compilation, su uso es el origen del origen, donde source es la ruta del model de Core Data para comstackr y el destino es la ruta del resultado.

Por "/ Developer / usr / bin /" significan " /Applications/Xcode.app/Developer/usr/bin/ "

Puede agregar un script en su esquema de destino y comstackrlo automáticamente antes de cada compilation (o después, no creas que importa). Esto es en caso de que cambie el model durante el desarrollo.

Algo como esto:

 mkdir -p "${BUILT_PRODUCTS_DIR}/your_model_name.momd" momc "${SRCROOT}/your_model_path/your_model_name.xcdatamodeld" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/your_bundle_name.bundle/your_model_name.momd" 

@ Ricardo Santos estuvo casi allí. Creo que solo necesitas convertirlo en una extensión "madre" en lugar de "momd", luego se ejecutará.

 lazy var managedObjectModel: NSManagedObjectModel = { let modelURL = NSBundle(forClass: self.dynamicType.self).URLForResource(self.dataModelName, withExtension: "mom")! return NSManagedObjectModel(contentsOfURL: modelURL)! }() 

El recurso model ya no es accesible a través de mainBundle , debe usar bundleForClass: así:

 NSURL *modelURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"MyApp" withExtension:@"momd"]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 

Supongo que solo requiere el model de datos.

Si es así, encuentro que el siguiente es consistentemente el método más exitoso para copyr en un file de model de datos de un proyecto a otro …

  1. Elimine las copys actuales del file .xcdatamodeld que reside en el proyecto de destino.
  2. Cerrar Xcode.

    Usando Finder (o línea cmd);

  3. Seleccione su carpeta de proyecto Xcode que contiene el file .xcdatamodeld original.
  4. Haga una copy del file .xcdatamodeld original.
  5. Mueva la copy del file .xcdatamodeld original a su proyecto de destino.

    Entonces…

  6. Abra Xcode.
  7. Con el command de menu "Agregar files a> su proyecto <", busque y agregue la copy del file .xcdatamodeld original a su proyecto.
  8. Cambie el nombre del file .xcdatamodeld original (si es necesario) usando Project Navigator.
  9. "Construir y ejecutar" su proyecto objective.

¿Ayuda esto?

Si intenta tener datos centrales en su marco, haga esto.

en YourFramework – agregar nuevo file / datos básicos / model de datos … – crear todos los objects …

Al crear un nuevo proyecto que utilizará YourFramework, asegúrese de que los datos principales estén activados. Usar datos básicos: en

Esto creará toda la placa de la caldera dentro de AppDelegate.

en Proyecto de testing – agregar Framework – agregar Framework como marco embedded – ELIMINAR file .xcdatamodeld – en AppDelegate:

cambiar - (NSManagedObjectModel *)managedObjectModel método - (NSManagedObjectModel *)managedObjectModel en:

 NSBundle * testBundle = [NSBundle bundleWithIdentifier:@"YourFramework bundle id "]; NSURL *modelURL = [testBundle URLForResource:@"Model" withExtension:@"momd"]; 

donde el YourFramework bundle id es el identificador de package de YourFramework (en general / identificador de package)

y Model es el nombre de su file .xcdatamodeld en YourFramework

Esto funciona.

Espero eso ayude.