This is usually found in quick&dirty code samples, to define constants. You can also see it in many older APIs, where various constants were defined this way.
This is bad. It works, but it’s lazy.

#define is pre-processor directive and should not be used to define numbers and strings that will then be used as part of the actual code. It’s a hard-coded value that lives in its own memory space, outside of your regular scope.

Use proper, modern stuff that Objective-C offers and Xcode supports very well.

Constants

To define a global constant for, say a notification name, do it like this in .h file (above @interface part):

extern NSString * const RDMDataManagerDidBecomeReadyNotification;

and then in .m file (also at the top, above interface/implementation):

Works great, it’s pretty clear, especially with very elaborate prefix that namespaces the notification to my DataManager class.

If you have way too many of these constants, the repetitiveness can become boring to type and seriously hurt code readability. In that case I recommend to use this neat way to struct them together (and even more clearly namespace them). In .h file:

You can also define just a starting value and then leave the rest to increment by one. You can reset the current value to anything, at any point. This is my favorite way to define constants for cells in multi-sectioned table view:

Using bit-shifting in the definition, you not only define a set of distinct values on their own but any combination of them – made using bitwise OR (|) – will also be distinct.

Inside your method, you then use bitwise AND (&) to check what options are set:

if (flags & UIViewAutoresizingFlexibleRightMargin) {
…
}

If you want to remove a specific option:

flags &= ~UIViewAutoresizingFlexibleRightMargin;

One great usage of this is, again, to increase code readability as well as simplicity. Say I have a method that takes JSON array returned from some API and I now need to parse the object, but I need to be able to specify what operations should be done regarding the already existing objects: insert new, delete obsolete, update existing.

The true value of this approach reveals itself when you need to add more actions at some moment. Your method signature remains the same, all possible places that call the method are thus un-affected. Your existing code inside the method also stays the same as it was; you simply add new if (actions & RTProcessActionXX) block and work done.