Refer to higher directory in #import statement Objective C - objective-c

I am using Mogenerator to automatically create subclasses for my Entities in Core Data.
I had acted upon a recommendation I read to store the files in subdirectories within my project (since I will have many). Used the following arguments when running the script:
cd Project
mogenerator --template-var arc=true -m Project.xcdatamodeld/Project.xcdatamodel/ - M CoreData/Machine/ -H CoreData/Human/
I added these to my project as a folder reference, as the script may add files to match my model and I don't want to have to add them to my project manually.
The directory structure for both the created files are like this:
Project/CoreData/Human/Entity.h
Project/CoreData/Machine/_Entity.h
I need to import "_Entity.h" inside of "Entity.h". The problem is, it's not in the same or lower directory and I don't know how to do a relative reference to a higher directory. I'm forced to use an absolute directory all the way from /Users.. which works, but it includes my username etc. so I'd rather not.
Question: How can I import _Entity.h from Entity.h using relative reference?
Bonus question: Is it possible to have mogenerator automatically use the proper reference? I mean, I'm clearly telling it where to put both files and it's doing it, but still only puts the following in Entity.h:
#import "_Entity.h"
...and I get an error.
Thanks in advance,
Pat

".." (without the quotes) represents the directory that's "one level higher". Use this to go to "CoreData", then to "Machine".
Try this:
#import "../Machine/_Entity.h"
I'm not sure if it'll work, but it's worth a try!

Related

Get AST Nodes of objective-C class without resolving dependencies

I am trying to create a refactoring tool that would allow me to get a syntax tree from an objective-c class so that I can change the structure of the class and output a different version of it that matches my criteria. I am looking at Clang's Libtooling to generate an AST and then take it from there, the issue I'm having is that I need to somehow make sure I provice all paths to all possible headers that are being imported from this source, and that's something I'd like to avoid.
I am wondering if there is a way to generate the AST for a class without having to for example provide paths for the framework containing the class definitions of the properties that the class I wanna refactor hold.
Ideally I would be able to get nodes in raw text of my source file containing things like properties, functions, etc... this way I'd be able to traverse that tree and change its structure to later on regenerate my source in the desired way.
After doing more research I deveoped the understanding that what I was trying to do is not even possible as LibTooling based tools need syntactic and semantic information about a program. This information can be provided via a compile_commands.json file like stated on the documentation:
Clang Tooling needs a compilation database to figure out specific build options for each file. Currently it can create a compilation database from the compile_commands.json file
For Xcode projects, this file can be generated like this:
xcodebuild -project PROJECT_NAME.xcodeproj | xcpretty -r json-compilation-database --output compile_commands.json
you will need to install the xcpretty gem. (gem install xcpretty)
Source: https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html

play 2.x organize templtes folder structures

How to organize folder structures in app/views folder without conflicting with other application folders? For example,
app/
controllers/
org/
OrgInfo.scala
views/
org/
a.scala.html
user/
b.scala.html
I found out that b.scala.html can no longer see org.OrgInfo class. When I do #import org.OrgInfo at b.scala.thml, it throws an error that it can't find OrgInfo under views.html.org. What's wrong?
Scala accepts relative packages, this means that if you try to use org like that it refers to the views.org package, you can solve this by providing the fully qualified class name:
#import controllers.org.OrgInfo
I think johanandren provided you with the correct answer.
So you should not start your import clause from org. org in your case is a sub-package of controllers. Use the absolute package name controllers.org._

Xcode search paths for public headers in dependencies

I am trying to clean up some of my projects, and one of the things that are puzzling me is how to deal with header files in static libraries that I have added as "project dependencies" (by adding the project file itself). The basic structure is like this:
MyProject.xcodeproj
Contrib
thirdPartyLibrary.xcodeproj
Classes
MyClass1.h
MyClass1.m
...
Now, the dependencies are all set up and built correctly, but how can I specify the public headers for "thirdPartyLibrary.xcodeproj" so that they are on the search path when building MyProject.xcodeproj. Right now, I have hard-coded the include directory in the thirdPartyLibrary.xcodeproj, but obviously this is clumsy and non-portable. I assume that, since the headers are public and already built to some temporary location in ~/Library (where the .a file goes as well), there is a neat way to reference this directory. Only.. how? An hour of Googling turned up blank, so any help is greatly appreciated!
If I understand correctly, I believe you want to add a path containing $(BUILT_PRODUCTS_DIR) to the HEADER_SEARCH_PATHS in your projects build settings.
As an example, I took an existing iOS project which contains a static library, which is included just in the way you describe, and set the libraries header files to public. I also noted that the PUBLIC_HEADERS_FOLDER_PATH for this project was set to "/usr/local/include" and these files are copied to $(BUILT_PRODUCTS_DIR)/usr/local/include when the parent project builds the dependent project. So, the solution was to add $(BUILT_PRODUCTS_DIR)/usr/local/include to HEADER_SEARCH_PATHS in my project's build settings.
HEADER_SEARCH_PATHS = $(BUILT_PRODUCTS_DIR)/usr/local/include
Your situation may be slightly different but the exact path your looking for can probably be found in Xcode's build settings. Also you may find it helpful to add a Run Script build phase to your target and note the values of various settings at build time with something like:
echo "BUILT_PRODUCTS_DIR " $BUILT_PRODUCTS_DIR
echo "HEADER_SEARCH_PATHS " $HEADER_SEARCH_PATHS
echo "PUBLIC_HEADERS_FOLDER_PATH " $PUBLIC_HEADERS_FOLDER_PATH
.
.
.
etc.
I think that your solution is sufficient and a generally accepted one. One alternative would be to have all header files located under an umbrella directory that can describe the interface to using the depended-on libraries and put that in your include path. I see this as being similar to /usr/include. Another alternative that I have never personally tried, but I think would work would be to create references to all the headers of thirdPartyLibrary from MyProject so that they appear to be members of the MyProject. You would do this by dragging them from some location into MyProject, and then deselecting the checkbox that says to copy them into the project's top level directory. From one perspective this seems feasible to me because it is as if you are explicitly declaring that your project depends on those specific classes, but it is not directly responsible for compiling them.
One of the things to be wary of when addressing this issue is depending on implementation-specific details of Xcode for locating libraries automatically. Doing so may seem innocuous in the meantime but the workflows that it uses to build projects are subject to change with updates and could potentially break your project in subtle and confusing ways. If they are not well-defined in some documentation, I would take any effect as being coincidental and not worth leveraging in your project when you can enforce the desired behavior by some other means. In the end, you may have to define a convention that you follow or find one that you adopt from someone else. By doing so, you can rest assured that if your solution is documented and reproducible, any developer (including yourself in the future) can pick it up and proceed without tripping over it, and that it will stand the testament of time.
The way we do it is to go into build target settings for the main project and add:
User Header Search Path = "Contrib"
and check that it searches recursively. We don't see performance problems with searching recursively even with many (10-15 in some projects) dependencies.

How do the Mogenerator parameters work, which can I send via Xcode? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
The help for Mogenerator is very minimal. What do all the parameters do?
Parameters that work both via the command line utility and Xcode:
--base-class: The name af the base class which the "private class" (e.g. _MyObject.h) will inherit from. This will also add an import in the form of #import "MyManagedObject.h" to the same .h file. Tip: if the class you want to inherit from is located in a library, the default import statement won't work. As a workaround, you could have an extra level of inheritance for each project you create and have that class inherit from the library on (e.g. set the base class to MyProjectManagedObject which you create manually and inherit from MyLibManagedObject).
--template-path: The path to where the 4 .motemplate files are located. When this is not provided, it will look at all the "app support directories" (e.g. "/Library/Application Support/mogenerator/").
--template-group: A subdirectory name underneath the template-path directory to use.
--template-var arc=true: Required for the generated files to compile while using ARC.
--output-dir: The output directory for all generated files.
--machine-dir: The directory where the _<class>.h and _<class>.m will be output to. If --output-dir is also defined, this parameter takes precedence.
--human-dir: The directory where the <class>.h and <class>.m will be output to. If --output-dir is also defined, this parameter takes precedence.
--includem: the full path to a file that will include all the #import for all the .h files that are created. This file does not need to exist (i.e. it will be created for you if it doesn't). This file, will not be included in the project automatically for you. You must include it manually by dragging it into the Groups & Files list of your project.
Using relative paths in Xcode for any of the above arguments won't work since the working directory is set to one of the root directories of the system (e.g. Applications, Developer, Library, or System). (I haven't had enough time to figure out which one of these it is exactly.)
Parameters that cannot be used in Xcode:
--model: The path to the .xcdatamodel file, cannot be set in Xcode.
--list-source-files
--orphaned
--versioned
--help
Running and sending parameters to xmod via Xcode:
(Update: I haven't tried this on Xcode 4, only Xcode 3. For Xcode 4, you can add mogenerator as a build phase instead of following the following steps.)
Go to the info page of the .xcdatamodel file.
Choose the Comments tab.
Add xmod to the comments field, on its own line.
Every time you save the model, it will regenerate the machine files for you.
To send parameters, they must be on their own line(s):
This works:
xmod
--base-class CLASS
--template-path PATH
And even this works:
xmod
--base-class CLASS --template-path PATH
But, this won't work:
xmod --base-class CLASS --template-path PATH
Note: You must close the Info window for the settings to take effect.
As of XCode 4, the Info window is no longer available, so don't be concerned if you can't set it up as answered above.
Use John Blanco's guide to set up a scripting target which allows you to pass command-line arguments directly to mogenerator. Note that you might have to tweak the paths in his example slightly... toss a pwd in the script and check the paths against the script's working directory if it doesn't run for you right away.
For a list of available command-line arguments, run mogenerator --help in the Terminal. AFAICT, all of them work from the scripting step.
See this answer for another way to invoke mogenerator via a "pre-action" if you want to automatically rebuild your machine files with every build. There's also a good tip on putting a mogenerator script into your VCS.
Here is the output from --help as of version 1.27
mogenerator: Usage [OPTIONS] <argument> [...]
-m, --model MODEL Path to model
-C, --configuration CONFIG Only consider entities included in the named configuration
--base-class CLASS Custom base class
--base-class-import TEXT Imports base class as #import TEXT
--base-class-force CLASS Same as --base-class except will force all entities to have the specified base class. Even if a super entity exists
--includem FILE Generate aggregate include file for .m files for both human and machine generated source files
--includeh FILE Generate aggregate include file for .h files for human generated source files only
--template-path PATH Path to templates (absolute or relative to model path)
--template-group NAME Name of template group
--template-var KEY=VALUE A key-value pair to pass to the template file. There can be many of these.
-O, --output-dir DIR Output directory
-M, --machine-dir DIR Output directory for machine files
-H, --human-dir DIR Output directory for human files
--list-source-files Only list model-related source files
--orphaned Only list files whose entities no longer exist
--version Display version and exit
-h, --help Display this help and exit
Implements generation gap codegen pattern for Core Data.
Inspired by eogenerator.
Also, maybe will be helpful.
For determining which params can be used for
--template-var KEY=VALUE
open *.motemplate file, and find string like "TemplateVar." after point you will see parameter name and will able to understand what it do.
This params has built-in template
--template-var arc=true
--template-var frc=true
--template-var modules=true

Best practices when importing class files in xcode

I'm working with xcode and I have classes associated with other projects that I want to be included in new projects. I realize that the #import will do the job technically (although what should i do if it's out of the project root folder). But what do I do if I want to include the class "properly" --basically so i can double click and edit out of the main project window where you can see all your files and such.
I guess I'm just looking for the best and/or proper way to include/import (into the project) .h and .m files that I've already created outside of the current project I'm working on. Taking into consideration that I may want to modify the class from the original without subclassing. Hopefully this makes sense.
Thanks,
Nick
Xcode project file organization doesn't reflect the data files on disk. Files can be added to a project from anywhere in the file system. When you add the files, choosing not to copy the files to the current project's directory means that the original files are used. Selecting one of these files in Xcode for editing will alter the original file in that other project. When returning to that other project, Xcode will use the edited files in any further work.
This type of use can be quite handy while working on multiple projects with some shared code. Yet, it can also cause headaches for a versioning system.
Might be worth thinking about how to make the classes into a private framework - then you can import that as another dependency each time. Alternatively you could use a separate version control system location to store the shared classes and just check that out into the project folder.