So I think I have this kinda clear, based on this blog post and my experiments:
what's included by #import MyPod; is the auto-generated MyPod-umbrella.h header, which imports all the public headers according to the Podspec
the auto-generated module map also permits explicit import of those and only those same public headers
what's included by #import <MyPod/MyPod.h> header is a MyPod.h header that I still need to make, but it can import anything I choose that's in the module map
What I was hoping to achieve, however, was that the header for either #import or #import to include most but not all of my pod's public headers. I'd like one of my public headers contain optional declarations that are normally omitted, to only be included manually from the few .m files that need it. But it seems to not be possible when code uses #import since the includes in that umbrella header always matches all the public headers.
Specifying a custom module map is possible and would work, but doing that seems to precludes the benefits of auto-generated map & umbrella header.
Would it be kosher to do some macro & #ifdef tricks to skip the contents of my "optional" header when included by the #import but then use the contents if that header is pulled in again with an #include? This sounds ugly, but is it my only option?
I found problems with all the #ifdef tricks I attempted when using framework cocoapods, though I'm sure they'd work when not. But I don't really want to be biased against frameworks and would like a solution for both.
So to take another approach, I found its not hard for a project to access a pod's private headers! See here and here (that last tip is for Swift, but I'm sure the right #import will work in Objective-C too).
So in my cocoapod I'm going to make the optional header private, and then rely on my users to use those methods to access it if desired.
Related
I have this code base which is Objective C and Swift mix. Some places Swift uses Objective and and vice versa. I need to create a framework now based of off this codebase but do not want to include all the objective c files in my umbrella header. Here's my problem:
Inside my framework I still need to be able to use swift from objc and vice versa; but do not want to expose all those objc files that are being used internally by swift classes. Bridging header is not allowed in frameworks so all the headers needed by swift need to go in umbrella header.
I'm wondering if it's possible to have all the objc headers needed by internal swift code go in a file which would be my private umbrella header and all the files that I need to expose would go in public umbrella header.
Any suggestions?
I am successfully using explicitly declared modules as a solution of sorts for this issue for the Objective-C -> Swift case. I have not separated the module declaration into a separate private module map but declared both the framework module and an explicit module inside the same modulemap because of the concern raised in one of the comments to the question (I wasn't sure if or how it is possible to use the header generated by the private module map inside the same framework).
Here's an excerpt of the modulemap I have defined for my MPFoundation.framework, which includes an explicit module MPManuscriptCompiler_Protected that imports the header "MPManuscriptCompiler+Protected.h" which is not included in the umbrella header for the framework:
framework module MPFoundation {
umbrella header "MPFoundation.h"
export *
module * { export * }
explicit module MPManuscriptCompiler_Protected {
header "MPManuscriptCompiler+Protected.h"
export *
}
}
I then use this explicit module MPManuscriptCompiler_Protected in my Swift subclass which is present in the same framework like so:
import MPFoundation.MPManuscriptCompiler_Protected
My solution is really technically just a workaround though: for this to work, "MPManuscriptCompiler+Protected.h" can be marked a private or project level header in the framework, so it will not be visible in the umbrella header and will not be available for header based imports with its filename. So, this works around having to include this header in the umbrella header.
However, the module created this way is publicly exposed in the framework and available for eyes that should not see it. I did not investigate this further as practically this solves the issue well enough (am yet to hit issues where I would have by accident imported that protected header where it wasn't supposed to be imported).
I'm doing some reorganizing of a semi-large project and I'm not sure the best way to go about it. I cannot decide where to use my #imports <...> across multiple files. I have a "Settings.h" style header that contains a lot of #define's needed by many of my classes. Should I be #importing everything needed by a class into its header? Or should I not import anything into the header and use #class definitions, then save the #import for the actual class.m files?
If this is unclear, let me know and I'll try to reiterate.
Where possible, prefer #class over #import in header files.
Result: faster builds and less likely to creaty circular dependencies (A imports B, B imports A).
You can also create a header file that #imports commonly used headers or those headers that are commonly used together, so that you don't need to #import each header individually.
After several months of coding in Objective-C, I completely understand when I need an #import, how import statements cascade (ripple?), and when to use forwarding classes. I do not know how to aggregate imports to get them inside of <> instead of in quotes (although maybe that's just for frameworks)...
The problem is that I'm making a huge mess. I come from Java (and the heavy-handed IDE), so I just add imports as I see fit. Sometimes I add them to the interface, but since that's usually not necessary, I just add them to the top of the .m in question.
Today I started thinking: there must be some rules of thumb on how to organize this stuff. In fact, since Objective-C is a C superset, there are rules of thumb for everything, but I don't know them. How should I organize my imports? Particularly:
When should I import in the .m?
When should I import in the .h?
Should I create .h files just for the sake of importing them (i.e., header files that just have imports in them)? If so, any hints on organizing that?
This is just a general idea of what I'm trying to figure out.
The <....> syntax is indeed just for frameworks. That doesn't mean you shouldn't create a framework to contain the core logic of your application though. Often this is a useful thing to do if you:
a) Need to provide support for loadable bundles that want to invoke aspects of your application logic (the bundle links to the framework, so does your application)
b) Write multiple apps that share the same core logic
Your question is somewhat subjective and you will get developers who argues both ways, but a convention I follow is:
Never import class definitions in the .h file, unless you are subclassing it. Use forward #class directives for everything in the .h.
Only import class definitions into a .m as you find you need to use that class in the implementation.
Generally speaking, the .h does not need access to the class definition of its ivars, method arguments or return values. It only needs to know that they are classes, which is what #class allows you to do. It does need access to the class definition of anything you're subclassing, adding a category to, or (obviously) implementing a protocol for.
Forget about whether <...> is for frameworks or what. <...> checks the system header search path, while "..." checks the current dir in addition to. One thing to remember however, is that the <CoreFoo/CoreFoo.h> declaration is handled a little differently on the apple platform, but only as it relates to apple frameworks: CoreFoo.framework/Headers/CoreFoo.h is matched to CoreFoo/CoreFoo.h
When imports are inside <> instead of quotes, all this means is that you are importing something from a framework. In fact, when doing this, the import is typically in the style
#import <Foundation/Foundation.h>
The first Foundation, before the slash, is the name of the framework in question, and the second one is just a header file in that framework. That header file is just something like
#import <Foundation/NSObjCRuntime.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSAutoreleasePool.h>
...
#import <Foundation/NSURLHandle.h>
including every file from that framework. You can do this too, and isn't a bad idea for components that need multiple imports (although in that scenario, you may want a separate public interface)
For the other stuff, following the rule of thumb that you want stuff to know about as little as possible, you only want to put the import in the header file if it's necessary (like for an ivar or superclass) but really it's a matter of taste.
I was just wondering if I have the option to specify more than one set of class declarations and definitions in the same file, without breaking it up into multiple files.
I'm guessing this is just the sign to break it up, but I was just wondering out of curiosity.
Also, bonus, when including, what is the difference between #include and #import.
Yes. The only really vital division is that a file should only be imported or compiled, not both — that is, unless all the code you feed to the compiler is in main.m, you need to have at least one header and one implementation file. The header can contain all the interface details for everything in your program and the implementation file can contain all the implementation details and it will work just like if you had separate files. You can just stack the contents of the would-be files end-to-end. That's actually what the #import and #include directives do — they literally copy the contents of the included file into the place where the directive is written.
Of course, what we're talking about here isn't a good design for a program at all.
Yes you can do that.
#import has built-in checks to prevent including the same file multiple times (avoiding stuff like #ifndef __MYHEADER_H...)
Yes you can have multiple classes in a same file but i don't prefer it. Its a good habit/good design to have classes in different files. Helps a lot in re-usability.
#import ensures that a file is only ever included once so that you never have a problem with recursive includes. I think performance may go down if use #include.
I have an idea on how to do this, but I want to make sure I do it right....
I have five data classes. When I use one I typically use all of them (but not always).
Each class has a separate header file. I am getting sick of linking in each header file separately.
What is the best way resolve this issue?
Create a new header file called "DataFiles.h". Inside that, have your five #import statements. Then whenever you need the file classes, just #import "DataFiles.h".
Beware of circular dependencies.
(This is how Cocoa, Foundation, UIKit, CoreData, etc all behave. Notice that you just #import <Cocoa/Cocoa.h>, which imports everything else. Open up Cocoa.h and take a look)