I'm using Simperium and mogenerator in my project. I've added SPManagedObject entity to the model and set that as the parent class for other entities. For each entity, mogenerator automatically creates a _<entityname>.h and _<entityname>.m file that has several convenience accessors. I've modified the mogenerator build script so each of these subclasses SPManagedObject instead of NSManagedObject. The entity classes simply import the corresponding _<entityname>.h file.
My problem is I'm getting runtime errors when using any of the convenience accessors. For example, for an entity with attribute of type Integer32 called myInteger, the class file property is NSNumber. Mogenerator creates an accessor named myIntegerValue. The errors I'm getting are that myIntegerValue is an unrecognized selector for SPManagedObject. I can work around this obviously but it seems to be indicative of a bigger problem. Any ideas? Thanks!
This kind of problem is most often the result of failing to configure the class name in the Core Data model editor. You may have a class Foo and an entity Foo but they don't automatically go together (they're not required to have the same name). If you don't do this, you get instances of NSManagedObject instead of instances of your subclass. And of course, NSManagedObject doesn't have those methods.
Select the entity in the model editor and look in the model inspector on the right. Make sure that the class name is configured.
Related
i am using jaxb to generate code from an xsd.
The generated code contains a lot of annotations; for classes and fields.
I am trying to use com.sun.tools.internal.xjc.Plugin to modify the generated code.
In the plugin run() method we are given an Outline class from which we can get ClassOutline. ClassOutline has an JDefinedClass final member which has the info about actual class which will be generated.
If i want to add anything, there are apis in JDefinedClass which can be used. But if i want to remove something, there is no way.
e.g. i cannot clear annotations, because the JDefinedClass.annotations() method returns an UnmodifiableCollection. so i cannot clear it or remove anything from it.
i tried to create another JDefinedClass by invoking the _class method but the ClassOutline.implClass variable is final, so i cannot set it.
how to get a JDefinedClass which does not have any annotations?
is there another phase of code generation which i can trap into to really control the generation of JDefinedClass?
The code model is, indeed mostly "write only". But, speaking of annotations, you have probably missed the methods like com.sun.codemodel.JDefinedClass.removeAnnotation(JAnnotationUse) and com.sun.codemodel.JMethod.removeAnnotation(JAnnotationUse) (implemented from com.sun.codemodel.JAnnotatable.removeAnnotation(JAnnotationUse)).
So they're there. You can remove annotations with the normal CodeModel API.
As I can see, you can also remove fields and methods from classes. So what exactly are you missing?
JDefinedClass.annotations() It return an unmodifiable collection object and you cannot modify them.
So work around for this, you can restrict annotation addition/deletion at class and field level before building JCodeModel.
You need to create a custom Jackson2Annotator class which extends Jackson2Annotator and override their methods according to your requirement.
Following are few methods which are being used for specific type of annotation property:
propertyOrder(OTB JsonPropertyOrder)
propertyInclusion(OTB JsonInclude)
propertyField(can be used for custom defined annotation at field level)
More you can discover by looking Jackson2Annotator class what fit into your need.
We use early-bound class for development. But occasionally we use attribute names.
There is a way to do it using reflections, but reflections are not allowed in sandbox plugins.
What are the approaches to getting an attribute from proxy types without relying on reflections?
Opportunity.OpportunityId.AttributeName
You have a couple options:
You can use a RetrieveEntityMetadata to the list of attributes that the entity contains. You won't be able to use any early binding here, but you can inspect the results at run time to see what are valid attributes for the entity.
You could also create a simple utility that uses reflection to auto-generate a class or enum that contains the list of attributes before you actually deploy. Just add the class to your plugin dll and you'd have the benefits of early binding of entity attributes when developing your plugin, without having to do reflection at runtime.
Is there a bulit-in way to obtain an entity name from the class object of an NSManagedObjectSubclass? I know that this can be readily determined from an instance of a subclass, but I want to ask the class itself. I can write a class function, but I would rather do this introspectively.
You can do it now by executing NSManagedObject.entity().name where NSManagedObject() is your subclass.
Check out mogenerator if you haven't already.
http://raptureinvenice.com/getting-started-with-mogenerator/
It adds a lot of missing features to core data. In particular it keeps you from having to regenerate your entity classes.
You could iterate thru the key values of the entities in the context:
[managedObjectContext registeredObjects];
I've been using Metro and have come across a problem whereby wsgen seems to ignore any JAXB annotation that I put on web method response classes.
I'm trying to return a set of entity classes that I want to expose to external clients via a web service, however I only want to make certain class attributes and methods visible to external clients, so have set the class access type to be PROPERTY, and have annotated all attributes I want to be part of the XML version of the class with #XmlElement.
I can create the XML schema for the entity class using the schemagen ant task, which correctly ignores any attribute or method that I have not annotated with #XmlElement, however when I run wsgen to create the wsdl for the web service which has a method which returns a set of the entity class, then I get a java.lang.NoClassDefFoundError. This appears to be because wsgen is not ignoring a public method on the entity class that it should do, with the class referenced by the exception being a parameter to this method.
I've tried to annotate the method with #XmlTransient so that wsgen ignores it, but to no avail. If anyone can suggest what I should do to get wsgen to pay attention to my annotations then that would be great.
An annotated field/property will always be processed regardless of accessor type. You need to specify #XmlAccessorType(XmlAccessType.NONE) if you only want annotated fields/properties to be treated as mapped.
For More Information
http://blog.bdoughan.com/2012/04/jaxb-and-unmapped-properties.html
I'd like to place some custom methods directly into each NSManagedObject. Think, "calculated fields": these methods provide read-only calculated values based upon persistent values on the Entity - which is identical to this question.
I'm using the Xcode New File... Wizard to create NSManagedObject subclasses for each of my Entities. I'm trying to benefit from the system auto-creating the accessors for me. For example:
Core Data Entity: "Site"
#interface Site : NSManagedObject
As I continue to add new Attributes to my Entities, I'm replacing their corresponding NSManagedObjects by using the Wizard. When each file is replaced, my custom methods are lost.
Should I create my custom methods elsewhere so that I can continue to leverage the Wizard? Or, should I keep the methods on the NSManagedObject and add Accessors for new Attributes manually? Is there another approach?
Create a category on your NSManagedObject subclass:
In the "New File ..." dialog, choose "Objective-C category".
Create a category "CustomMethods" on "Site".
Xcode will create files Site+CustomMethods.h, declaring the #interface Site (CustomMethods), and Site+CustomMethods.m for the corresponding implementation.
Add your custom methods to the category.
These files will not be overwritten when you recreate Site.m and Site.h in Xcode.
All category methods can be used as if they had been declared in the class itself. The only thing you can not do in a category is add new instance variables.
Once I have used the wizard to create the initial managed objects, I generally change them manually.
Another way of doing this is to create subclasses of the wizard generated class files and use these.
When they are regenerated, all of your custom code is in the subclass, as opposed to the overwritten class file.