reproduce - no aparece mi musica en mi iphone
datos básicos en una biblioteca estática para el iPhone (8)
Creé una biblioteca estática que hace un uso intensivo de la infraestructura Core Data. Puedo utilizar con éxito la biblioteca en mi proyecto externo, pero SOLAMENTE si incluyo el archivo .xcdatamodel en el proyecto principal. Eso es menos que ideal, ya que el objetivo de la biblioteca era ocultar los detalles de implementación al máximo posible.
En otra question , me informaron que no puedo agrupar recursos con una biblioteca (lo cual tiene mucho sentido para mí ahora).
Entonces, ¿hay alguna manera de permitir programáticamente que el modelo sea "descubierto" sin tener que incluir el modelo en el proyecto principal?
La respuesta de Prairiedogg está un poco desactualizada, aquí hay un tutorial sobre cómo hacer esto en Xcode 5: http://bharathnagarajrao.wordpress.com/2014/02/14/working-with-core-data-in-a-static-library/
La respuesta de Sascha me puso en el camino correcto. La fusión de un archivo .mom
compilado de una biblioteca estática en el archivo .mom
de un proyecto de host fue relativamente simple. Aquí hay un ejemplo trivial:
Cree un nuevo proyecto de XCode Static Library llamado
MyStaticLibrary
Cree un archivo .xcdatamodel en
MyStaticLibrary
llamadoMyStaticLibraryModels.xcdatamodel
, agregue algunasEntity
, luego genere los encabezados y las implementaciones. Cuando crea el destinoMyStaticLibrary
, generará un archivo binariolibMyStaticLibrary.a
, pero no incluirá el archivo.mom
compilado. Para eso tenemos que crear un paquete.Cree un nuevo objetivo de compilación del tipo
Loadable Bundle
, que se encuentra enMacOS X > Cocoa
, llamemos al nuevo TargetMyStaticLibraryModels
.Arrastre
MyStaticLibraryModels.xcdatamodel
en la fase deCompile Sources
MyStaticLibraryModels.xcdatamodel
Compile Sources
delMyStaticLibraryModels
Target. Cuando construya el TargetMyStaticLibraryModels
, generará un archivo llamadoMyStaticLibraryModels.bundle
y contendrá el archivo compiladoNSManagedObjectModel
,MyStaticLibraryModels.mom
.Después de
MyStaticLibrary
tantoMyStaticLibrary
comoMyStaticLibraryModels
Targets, arrastrelibMyStaticLibrary.a
(junto con los archivos de encabezado de modelo asociados) yMyStaticLibraryModels.bundle
en su proyecto de host,MyAwesomeApp
.MyAwesomeApp
usaCoreData
, tiene su propio archivo.xcdatamodel
que se compilará en un archivo .mom durante su propio proceso de compilación. Queremos fusionar este archivo.mom
con el queMyStaticLibraryModels.bundle
enMyStaticLibraryModels.bundle
. En algún lugar del proyectoMyAwesomeApp
, hay un método que devuelve el objetoMyAwesomeApp
NSManagedObjectModel
. La plantilla generada por Apple para este método se ve así:
...
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel_ != nil) {
return managedObjectModel_;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyAwesomeApp" withExtension:@"momd"];
managedObjectModel_ = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return managedObjectModel_;
}
NSManagedObjectModel
esto para fusionar y devolver AMBOS de nuestros NSManagedObjectModel
, MyAwesomApp
y MyStaticLibraryModels
, como un único NSManagedObjectModel
combinado así:
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel_ != nil) {
return managedObjectModel_;
}
NSMutableArray *allManagedObjectModels = [[NSMutableArray alloc] init];
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyAwesomeApp" withExtension:@"momd"];
NSManagedObjectModel *projectManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
[allManagedObjectModels addObject:projectManagedObjectModel];
[projectManagedObjectModel release];
NSString *staticLibraryBundlePath = [[NSBundle mainBundle] pathForResource:@"MyStaticLibraryModels" ofType:@"bundle"];
NSURL *staticLibraryMOMURL = [[NSBundle bundleWithPath:staticLibraryBundlePath] URLForResource:@"MyStaticLibraryModels" withExtension:@"mom"];
NSManagedObjectModel *staticLibraryMOM = [[NSManagedObjectModel alloc] initWithContentsOfURL:staticLibraryMOMURL];
[allManagedObjectModels addObject:staticLibraryMOM];
[staticLibraryMOM release];
managedObjectModel_ = [NSManagedObjectModel modelByMergingModels:allManagedObjectModels];
[allManagedObjectModels release];
return managedObjectModel_;
}
Esto devolverá el NSManagedObjectModel
fusionado con Entity
s de MyAwesomeApp
y MyStaticLibrary
.
La solución de Sascha Konietzke funciona bien, pero hay una advertencia importante que debe proporcionarse para que funcione. El paquete que contiene el modelo debe cargarse primero; de lo contrario, no se incluirá en la matriz y se fusionará en la MOM.
En este caso, probablemente ya haya accedido a los recursos del paquete, por lo tanto, el paquete ya estaba cargado antes de que se ejecutara este código.
No, la limitación de usar frameworks que no son de Apple en una aplicación de iPhone realmente cambia el juego de dependencia en relación con OS X. La mayoría de los "frameworks" de iPhone (por ejemplo, la caja de herramientas de Google para Mac, Core Plot, etc.) realmente recomiendan incluir la fuente en su proyecto de aplicación principal en lugar de vincular un producto (es decir, una biblioteca estática). Creo que el consenso de la comunidad es que, en iPhone, está bien esperar que los consumidores de su infraestructura tengan que hacer un pequeño trabajo "manual" para usar su biblioteca. En su caso, esto incluye el archivo xcdatamodel en el proyecto principal. Al igual que con la mayoría de Objective-C, dígales a sus usuarios que no hagan uso de los detalles de implementación y déjenlo así.
Swift 2 versión para la respuesta de Sascha:
lazy var managedObjectModel: NSManagedObjectModel = {
// The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
var allBundles = NSMutableSet()
allBundles.addObjectsFromArray(NSBundle.allBundles())
allBundles.addObjectsFromArray(NSBundle.allFrameworks())
let model = NSManagedObjectModel.mergedModelFromBundles(allBundles.allObjects as? [NSBundle])
return model!
}()
También creé mi propia biblioteca estática que utiliza Core Data. Además de la biblioteca estática, tengo otro objetivo de paquete en el proyecto donde tengo un elemento de Copy Bundle Resources, que copia algunas imágenes y cosas así en el paquete y una fase de compilación Build Sources, donde estoy compilando el modelo xcdata.
El paquete final contendrá todos los archivos necesarios. En su proyecto principal que depende de la biblioteca estática, debe incluir ese paquete también. Su proyecto principal ahora tendrá acceso al archivo madre que se necesita para usar los datos centrales.
Para usar datos básicos con la madre del paquete, debe crear un modelo de objeto gestionado fusionado en su código (puede ser que el proyecto principal también tenga algún modelo de datos principal):
- (NSManagedObjectModel *) mergedManagedObjectModel
{
if (!mergedManagedObjectModel)
{
NSMutableSet *allBundles = [[[NSMutableSet alloc] init] autorelease];
[allBundles addObjectsFromArray: [NSBundle allBundles]];
[allBundles addObjectsFromArray: [NSBundle allFrameworks]];
mergedManagedObjectModel = [[NSManagedObjectModel mergedModelFromBundles: [allBundles allObjects]] retain];
}
return mergedManagedObjectModel;
}
Con solo incluir el paquete, no tendrá que dar el modelo xcdata, solo se debe incluir el archivo compilado de la madre.
También tengo una biblioteca con coredata. He encontrado esta plantilla para administrar un marco con recursos de inserción
es muy fácil de usar en un nuevo proyecto (más difícil de aplicar en el existente) pero para builds de framewoks, es realmente genial :-)
Tenga en cuenta que, en lugar de utilizar el archivo xcdatamodel / mom, también puede crear su modelo en código (especialmente si tiene un modelo simple) y de esta manera no necesitará crear un paquete adicional para los recursos. Aquí hay un ejemplo simple con una tabla que contiene dos atributos:
- (NSManagedObjectModel *)coreDataModel
{
NSManagedObjectModel *model = [NSManagedObjectModel new];
NSEntityDescription *eventEntity = [NSEntityDescription new];
eventEntity.name = @"EventEntity";
eventEntity.managedObjectClassName = @"EventEntity";
NSAttributeDescription *dateAttribute = [NSAttributeDescription new];
dateAttribute.name = @"date";
dateAttribute.attributeType = NSDateAttributeType;
dateAttribute.optional = NO;
NSAttributeDescription *typeAttribute = [NSAttributeDescription new];
typeAttribute.name = @"type";
typeAttribute.attributeType = NSStringAttributeType;
typeAttribute.optional = NO;
eventEntity.properties = @[dateAttribute, typeAttribute];
model.entities = @[eventEntity];
return model;
}
Aquí hay un tutorial sobre cómo crear un modelo a partir del código: https://www.cocoanetics.com/2012/04/creating-a-coredata-model-in-code/
También basado en este enfoque, creé una biblioteca pequeña y fácil de usar que podría adaptarse a sus necesidades llamada LSMiniDB para que pueda verificarla también.