I don't know Objective-C, so my answer will be about contrasting the use of the preprocessor in C and C++.
The preprocessor was originally necessary for C for several reasons. If I remember correctly, originally C did not have constants, so #define was needed to avoid magic numbers. Prior to 1999 C did not have inline functions, so again #define was used to create macros or "pseudo-functions" to save the overhead of a function call, while keeping code structured. C also doesn't have run-time or compile-time polymorphism, so #ifdefs were needed for conditional compilation. Compilers were typically not smart enough to optimize away unreachable code, so, again, #ifdefs were used to insert debugging or diagnostic code.
Using the preprocessor in C++ is a throwback to C, and is generally frowned upon. Language features, such as constants, inline functions, and templates can be used in most situations where in C you would have used the preprocessor.
The few cases where the use of a pre-processor in C++ is acceptable or even necessary include the guards for the header files, to prevent the same header from being included multiple times, #ifdef __cplusplus
to use the same header for both C and C++, __FILE__ and __LINE__ for logging, and a few others.
The preprocessor is also often used for platform-specific definitions, although C++ Gotchas by Stephen Dewhurst advises having separate include directories for the platform specific definitions, and using them in separate build configurations for each platform.