Date
1 - 9 of 9
Objective-C: What is the current preferred method of declaring constants without a .pch?
Alex Zavatone
I’ve read the Apple docs and looked around and can’t find definitive sources on what the preferred method is and how to do it.
Do we use modules? If so, how? I understand that a .pch is now a “bad idea”. OK. What do we do instead? Why? Is it good practice to create one constants.h/m? Or is that just another way of masking a global (which is bad)? It does make everything easy to find. Should we create one .h/.m file with multiple constants classes within? I can easily go back to using a .pch, but a clear path forward to the current year’s practice would be nice. Thanks in advance. - Alex Zavatone |
|
Steve Christensen <punster@...>
I use constants a lot, but I put their declarations and definitions into the "owner" class files. For example if one object sources notifications and others consume them.
toggle quoted message
Show quoted text
Foo.h extern NSString* const __nonnull FooNotification; Foo.m NSString* const FooNotification = @"FooNotification"; With Obj-C I have rarely ended up with true globals since I can create singletons as "global" instances of particular classes. I have created .h files containing some #defines that are used to conditionally compile certain features that may not be quite ready for primetime and so it could get pulled before an app ships. Steve On Oct 19, 2017, at 12:11 PM, Alex Zavatone <zav@...> wrote: |
|
Alex Zavatone
Thanks Steve. That’s one option I’ve been considering. It’s a balance between knowing where to look for everything and properly scoping some constant to the one place where I use it. If there’s one thing that wastes my time, it’s hunting through my project for a constant, but if it only needs to be in one place, then I probably should learn to expect looking for it in the class that uses it.
toggle quoted message
Show quoted text
FYI, if anyone needs a little more explanation of how to handle this with modules, I just found this relatively recent link that may help us stay current. It mentions how to use the umbrella header within modules if you’re using them. Also Ash Furrow has some good input. Thanks for your time everyone. - Alex Zavatone
|
|
Bernie Maier
Alex Zavatone:
I understand that a .pch is now a “bad idea”. OK. What do we doPre-compiled headers are now considered to be a bad idea, yes, but although traditionally the *prefix* header was usually pre-compiled it doesn't have to be. So what I use in some of my project is a prefix header that simply isn't pre-compiled. That said, I use it *extremely* sparingly, kind of like a more SCM-friendly place to define constants like conditional compilation flags that need to consistent across an entire build. These are often supplied as -D arguments to the compiler, and thus often live in relative obscurity amongst other project settings. Like others, I would normally attach more specific constants to whatever they are most related to. |
|
On Oct 19, 2017, at 12:11 PM, Alex Zavatone <zav@...> wrote:Wait, what? I never got the memo on this. Is it good practice to create one constants.h/m? Or is that just another way of masking a global (which is bad)?I put constants in the headers for the classes/APIs they are used with. If you look at Cocoa headers you can see Apple does the same thing. Also, this is a separate issue from whether to use a prefix or precompiled header. Ideally your code should be buildable without a prefix header, i.e. every source file should #import the headers it depends on. The precompiled prefix header is just to speed up builds. —Jens |
|
Steve Mills
On Oct 19, 2017, at 17:11, Jens Alfke <jens@...> wrote:Exactly. I’ve never heard anyone say they should no longer be used. Why wouldn’t you want faster builds?On Oct 19, 2017, at 12:11 PM, Alex Zavatone <zav@...> wrote:Wait, what? I never got the memo on this. Steve via iPad |
|
Fritz Anderson
I want faster builds. We all want faster builds. The question is whether precompiling text-substituted inclusions is the best we can do with a modern development system.
toggle quoted message
Show quoted text
The answer was yes when lexical insertion was the only way to impart context to a C-family source file. The answer should be no because the effect of a chain of #includes depends on the order they're done. If a.h says #ifndef FOO #undef FOO #define FOO bar #end and b.h says #ifndef FOO #undef FOO #define FOO baz #end Then it's really important (and impossible to document and surely intractable to debug) the order in which they are #included. Modules are precompiled and versioned against the environment in which that happened. Macro conflicts within a module are "ill-formed" and across modules they're local. Caveat that I'm drawing the details from memory and a cursory review of http://releases.llvm.org/3.5.0/tools/clang/docs/Modules.html . Further discussion should address the LLVM release note, not my memory. — F |
|
Quincey Morris
On Oct 20, 2017, at 07:29 , Fritz Anderson <anderson.fritz@...> wrote:
Except of course that the tradition of *pure C* programming has assimilated this as standard programming technique: the compilation of one package is modified by pre-inserting macro definitions that modify the outcome of the package’s own macro definitions. Indeed, the use of environment variables as macros available to the compiler is much the same thing. However, what I really wanted to say is that precompilation may still be useful *within* a large module such as the main application target. In that case, there may be a standard set of imports used in most source files, comprising multiple modules as well as multiple header files, and it *may* be beneficial to precompile all of that into a single, loadable file. I think a more accurate statement about precompiled headers would say: — Module inclusion is probably preferable to precompilation of the same declarations. — Precompilation of non-module (i.e. intra-target) declarations is of no use to Swift code because it doesn’t have monolithic, linear compilations like C does. |
|
Yup. When the target you’re building has enough of its own header files to affect compilation speed, it becomes useful to precompile them. There are also a lot of C and C++ headers in the OS (and in external libraries) that aren’t packaged into modules. For example, <sqlite3.h> is 10,000 lines long and it definitely helps to precompile it. —Jens |
|