After viewing the WWDC2013 LLDB Debug session, I want to add a custom type formatter for one my NSManagedObject subclasses. You can do this by typing in the debugger
type summary -add MyClass --summary-string "${var._name}"
This works but only on variables, not on methods, hence properties. I've also tried using a python script via valobj.GetChildMemberWithName without success.
How can I display a property on an NSManagedObject subclass on LLDB ?
More Info:
http://lldb.llvm.org/varformats.html
Long story short, as you realized the ${var.foo} syntax only works for ivars. Not for methods. Not for properties (which are methods, give or take syntactic sugar).
I have been thinking about a syntax to run expressions in the string summary format. It would look something like ${expr:[$var selector]} or ${expr:3+$var}
Lacking that, for now your workaround is to go to Python, and use the SBFrame.EvaluateExpression command. There are examples of Python formatters in the LLDB source code, and on the website that you can use as a starting point.
Related
One way of doing seemed to be to use the java.lang.Compiler
I tried to use the java.lang.Compiler inside Eclipse anddid not understand the Object any parameters for the methods of that class? And putting in a class did not seem to work either.
Compiler.command(any) // what is meant by any? What are valid objects to put there?
Compiler.compileClass(clazz) // Nothing happens when I out a class in there?
Compiler.compileClasses(string) // hm?
How to can I print a hello message with a Compiler inside Eclipse...?
Reading the documentation is a very important skill you need to learn.
Whenever you come across a class or a method that you don't know the functionality of, simply look at the documentation first.
Here is the docs for java.lang.Compiler: https://docs.oracle.com/javase/7/docs/api/java/lang/Compiler.html
This is the first sentence of the document:
The Compiler class is provided to support Java-to-native-code compilers and related services. By design, the Compiler class does nothing; it serves as a placeholder for a JIT compiler implementation.
So, the answer to your question is, it does nothing. According to the documentation, it does nothing. It is used to start up the Java compiler when the JVM starts. You are not meant to use this.
I've been using mogenerator for a while now, and while there is a reasonable Getting Started Guide and a Stack Exchange article on the command line options, I haven't found a good guide for all of the functionality it provides.
In short: what, above and beyond the classes that Core Data provides for you, what does mogenerator actually generate?
(Frankly, I kept finding little pleasant surprises in the headers/implementations that I didn't realize were in there and I decided to step through the mogenerator templates and code and document what I found in a Stack Exchange Q&A. I'd love to see additional answers and edits, however. )
In addition to its core feature of a two class system, mogenerator helps you by automatically implementing a number of best practices regarding Core Data in your machine header and implementation files.
Property Accessors
Methods to access the attributes of your Entities are the core of what mogenerator generates. But there are some nice features implemented in the accessors above and beyond what the out of the box Xcode class generator provides to you.
Scalar Accessors
Xcode's built in generator gives you the option of "use scalar properties for primitive data types". This option gives you choice of having Xcode create properties with NSTimeIntervals instead of NSDates for date types, BOOLs instead of NSNumbers for boolean types, and int16_t (or similar) rather than NSNumbers.
I find this infuriating because most of the time I prefer the primitive types, but not for NSDates which are much more useful than a NSTimeInterval. So Core Data is giving me the choice of objects, in which case I will be constantly unboxing stuff and making stupid mistakes like if(myBooleanAttribute) (which is always YES because myBooleanAttribute is a NSNumber, not a BOOL). Or I can have scalars, but in that case, I get NSTimeIntervals that I'll always have to convert to NSDates. Or I can hand edit all of the generated files by hand to give me my desired mix of NSDates and BOOLs.
On the other hand, mogenerator provides you with both options. For example, you will get both a myBooleanAttribute getter that gives you an NSNumber (for easy storage in an NSArray) and a myBooleanAttributeValue getter that gives you an actual BOOL. Same with integers and floats. (Mogenerator does not generate NSTimeInterval accessors: only NSDates.)
Typed Transformable Properties
If you have a transformable property, you can set a specific UserInfo key ( attributeValueClassName ) in the attribute that will specify the class that your property will return/accept. (And it will properly forward declare the class etc.) The only place I found this documented was on Verious.
In contrast, the Xcode code generator will only type these transformable attributes as id types.
Validation Declaration
While mogenerator does not automatically generate any validation methods, it does include the proper signature as a comment in the machine h file. The seems to largely be for historical reasons, but it does mean that it is easy to copy and paste the signature if you decide to implement it in your human file implementation. (I wouldn't actually uncomment the declaration as you aren't supposed to call validation directly.)
Primitive Accessors
Core Data already provides you these accessors to the primitive values, but for some reason doesn't include them in its Xcode generated headers. Having mogenerator include them in its header files makes it much easier to access a primitive value.
Fetched Properties
mogenerator will generate accessors for fetched properties. As far as I can tell there is no way to have the Xcode generator do this.
Helper methods
Automatic NSFetchedResultsController generation
If you have a to many relationship in your Entity and you pass --template-var frc=true into mogenerator, mogenerator will automatically generate a method to create a fetch request for the child objects associated with a parent object. It even automatically generates a unique cache name, and isolates everything inside an #if TARGET_OS_IPHONE preprocessor macro.
Even if this doesn't fit your particular needs, it is a great example of how the templates can be extended.
+fetchMyFetchRequest:moc_
If you like defining your fetch requests in the model, this is a lot better way to retrieve them than hardcoded strings.
-MyEntitySet
Mogenerator uses the magic of KVC to give you a NSMutableSet proxy into your relationships.
+entityName
Need to provide a entity name to a NSFetchRequest or other Core Data method? It's easy to avoid hard coded strings by using this simple method that returns the name of the entity as an NSString.
+insertInManagedObjectContext: and entityInManagedObjectContext:
Another way to avoid hardcoding entity names is to use these helper methods.
Typed object ids
Each of your headers and implementations also includes a MyEntityID class. They are empty interfaces and implementations that merely subclass the NSManagedObjectID class. Also, each model class has a helper method called objectID that overrides the standard objectID method in NSManagedObject. The helper method does nothing but cast the superclass's return value to the MyEntityID type.
The net result: the compiler can catch your mistakes if you ever accidentally interchange your object ids from different entities.
Miscellaneous
Subclassing a Custom Superclass
One of the command line options is --base-class: which allows you to specify a base class that all of your generated classes will inherit from. This is very useful, either so that you can have a base class where you define convenience methods (which, given Core Data, you probably should) or so you can use an off the shelf Core Data toolkit like SSDataKit (or both).
includem
A simple little thing, but if you specify a --includem argument, mogenerator will generate a header file that includes all of your model header files. Convenient if you want to include all of your headers in a PCH, or something some other standard header you include.
Const Definitions of All Attributes, Relationships, Fetched Properties
An extern declaration of a struct is included in the header that has an NSString defined for every attribute and relationship defined in your Entity. This allows you to define predicates and other parameters, without baking the names of your entities into your strings. For example,
req.predicate = [NSPredicate predicateWithFormat:
#"(%K == YES) AND (%K <= %#)",MyObject.favorite, MyObject.availableDate, [NSDate date]];
(This type of struct used for "namespaced" constants is described My Mike Ash on his blog
const Definitions of User Info Keys/Values
Similarly an extern declaration of a struct is defined in the header that includes the keys as members of the struct, and the values as a values. i.e.
NSLog(#"User info for key my key is %#",MyObjectInfo.mykey) //will log "myvalue"
Alternate Templates
One of the interesting things about mogenerator is that in building mogenerator its author (Wolf Rentzsch) has basically built a generic parser and templating engine for the xcdatamodel files produced by Xcode. So you don't need to use the mogenerator templates. You can provide your own with a simple command line argument. There are lots of user contributed templates on the GitHub site.
In fact, you don't even have to use Core Data. Many of the contributed templates allow you to generate a series of ordinary NSObject model classes based on the data model. (So called PONSOs: "plain old nsobjects"). Want to use the data modeler in Xcode, but some other persistence mechanism? mogenerator can help you there.
You don't even need to generate objects at all: another interesting submitted template just provides a diff of two different model versions.
I have been trying to use BLToolkit to activate an Oracle stored procedure which takes a User Defined Type as an argument as an output parameter and changes it.
I have managed to do this on a primitive type, and and also by manually calling SetSpCommamd however I would like to use the abstract class generation method but can't seem to get it to work.
I'm pretty sure the code I wrote is correct (works for the primitive). When debugging I found the SetSpCommamd called by the generated code gets wierd parameters instead of the ones I provided as opposed to when I call the method manually (the it gets the exact parameters I'd like). I wish I could see the code generated by the reflection emit to see what's wrong there.
Can anyone please help me figure out why this is not working?
Found the problem (Potentially a bug in BLToolkit).
BLToolkit does not pass the UDT Class as is to the procedure (instead it tries to flatten it or something and pass the insides of the object). I Changed the object to a Struct instead of a Class and that fixed it.
Later on I also changed it back to class and made a patch in the 'IsScaler()' method in BLToolkits code.
I will report this as a Bug I hope they fix it.
Xcode auto-generates the class implementations for your NSMO entities - great.
But we often need to customize them. If you ever forget that you customized these files, Xcode will happily "delete" (overwrite) and remove all your code.
So ... a classic trick was to:
Create the NSManagedObject's in Apple's model view
Generate the classes
Create new classes which use Categories to extend the original classes, adding the modified behaviour
Import the custom-category-headers rather than the base NSMO headers, thereby getting the "new" behaviour
This works great: put custom code in the category, and when you auto-generate files using Xcode, you never lose anything.
But ... now I'm using Bindings / Mac OS code, and Bindings are great, but I have no idea how to make a Binding "import" the derived header (with the category, and the modified methods / custom behaviour)?
e.g. if I have an ArrayController (very common) that's holding NSMO instances, you normally tell it the "Entity Name" (e.g. "MyCoreDataEntity"), and it requests the NSMO with that class name. But that will never load the category, so it will never pick up the customized version of the class.
How do you get around this? Either: how do you load in the category-version of a class?
OR: how do you write custom code without using categories and AVOID Xcode deleting all your code when it feels like it?
I must admit since I use cocoa touch there is no binding available - so I really do not know if my suggestion is applicable in your case.
However, maybe this helps?
There is an alternative to categories for core data additions - not as "sophisticated" as categories - I know.
One may use #include statements:
There are two alternatives:
create a new ClassFile, delete the include "header.h", (delete the header.h), put the extra code there. It compiles but brings the two warnings: (which are understandable) [WARN]warning: no rule to process file '$(PROJECT_DIR)/Classes/../included_dataStuff' of type text for architecture armv6 [WARN]warning: no rule to process file '$(PROJECT_DIR)/Classes/../included_dataStuff' of type text for architecture armv7
create a new "empty" file and put the extra code there. This does not produce any warnings.
The difference between 1 and 2 is that while the code formatting remains in the first alternatve (having to accept the 2 warnings) in the second all the code format is lost and its treated like normal text (but there is no warning)
I guess I would prefer the first. Of course, the only modification to the generated code file would be the #include statement.
The easiest solution would be to subclass NSArrayController, import the category and then use the subclass in IB. That way your bindings should automatically know of the category.
MoGenerator used to be good at generating custom classes without having to overwrite anything. I'm tinkering with updating it or something like it for Xcode 4.x since the original authors don't seem to have the time to do so.
Ok, I am creating a document-based application in Cocoa and the document's file type is actually a package. Within that package is an XML settings file, a SQLite database and a zip file which is downloaded at runtime. Now the only thing that changes, really, is the XML settings file as the other ones can be recreated at run-time.
Each one of these packages will have one and only one window, hence my desire to use document-based. These files can also be copied, renamed, moved, etc. just like any other file that is part of such an architecture.
But I am completely lost as how to implement this in the Documentation Framework! It seems everywhere I look in the docs it's always talking about in-memory representations of the files which you then write out using the path presented to you in one of the NSDocument overrides (since Cocoa may move it, etc.) But again, I'm using a SQLite database that sits on disk, not in memory.
I have looked all over for overridable methods that would still give me things like dirty-state checking of the doc, open and save file dialog support and the like, but I can't seem to find anything that just says 'Here's a file URL... Open it as you see fit' althought I did get close at the application's delegate level, at least for the opening.
So let's assume that's working as expected. How do I implement the save/save-as where I want to control everything that is written to disk or not? I don't want to (not can I) mess around with data structures or the like. I just want to be given a psth that the user selects in the 'Save As' dialog (for new) and be able to write what I need to there. Simple. But again, the 50+ page document from developer.apple.com about Document-based architecture tells me where to overload a lot of things, but every one seems to stem from some in-memory representation of the document, which again, is not what my package is. Technically, only the internal XML file is what would be tied to the document. Everything else is just support for it.
So? Anyone? Takers?
Mark
I can't seem to find anything that just says 'Here's a file URL... Open it as you see fit'
Implement the readFromURL:ofType:error: method in your document class. Alternatively, since your document type is a package type, implement the readFromFileWrapper:ofType:error: method.
You don't have to read the data into memory; you can do whatever you want in whichever method you implement, including opening the database.
How do I implement the save/save-as where I want to control everything that is written to disk or not?
Implement the writeToURL:ofType:error: method or the fileWrapperOfType:error: method.
If you had or could easily create data in memory, you would implement the readFromData:ofType:error: and dataOfType:error: methods. The URL-based and file-wrapper-based methods are for cases where data in memory is not an option. And the primary use of file wrappers is for package types like yours.
Actually, I found it. It's not the 'writeTo' methods, but rather the 'saveTo' methods you want to override. When I did that, the saving code worked as I expected, including automatic save panel support. For clarity, this is the one I chose...
saveToURL:ofType:forSaveOperation:error:
and it works like a champ! Not too confusing now, was it! Sheesh!!!
That was of course the very first thing that I tried, but if you read the developer documentation--specifically the Cocoa Document-Based Architecture--here's what it says about those very methods...
During writing, your document may be asked to write its contents to a different location or using a different file type. Again, your overridden method should be able to determine everything it needs to do the writing from the passed-in parameters.
If your override cannot determine all of the information it needs from the passed-in parameters, consider overriding another method. For example, if you see the need to invoke fileURL from within an override of readFromData:ofType:error:, perhaps you should instead override readFromURL:ofType:error:. For another example, if you see the need to invoke fileURL from within an override of writeToURL:ofType:error:, perhaps you should instead override writeToURL:ofType:forSaveOperation:originalContentsURL:error:.
In other words, it seems to say that you can't assume the URL that is passed to you is the actual place on disk where the 'something' is eventually written to, which wreaks havoc when dealing with database files that are opened by URL. Maybe I'm missing something.
But ok... forget I read that and simply even try to just override those methods. I do and return TRUE for each, (I log the URL so I can see what is being passed in), I get this error on 'Save As' after you have chosen a filename...
2009-10-28 14:31:51.548 XPanel[1001:a0f] dataOfType:error: is a subclass responsibility but has not been overridden.
...but when you look at the documentation for that it says the default implementation throws an exception because you must override one of the other implementations above... which I obviously just did! Plus, again, this can't be represented as simple data!
So grasping at straws here, I overrode that one too and just returned nil, since again, you can't represent what I'm doing with a NSData object. Then I get a 'Can't be saved' message.
WTF?! Why is it calling that thing anyway??!!
...and that's when I gave up and posted this here.
Now if YOU can give me a simple example that perhaps doesn't even actually read or write a file but instead just logs the URL, that would be perfect. Not to useful but still, it should work... I just can't seem to implement get it to.