SW engineering, engineering management and the business of software
Four broad categories of macros end up useful enough to find a home in the highly coveted precompiled header file.
For the sake of brevity, just the names of the macros are listed here, but you can find the full source at https://github.com/amattn/AMNGlobalUtilities/blob/master/GlobalUtilities.h
You should have your own set of useful macros that tend to follow you around. These are the one useful enough that I bring them along to new projects.
// Quickly make an NSError #define AMN_QUICK_ERROR(error_code, error_description) // Quickly get portrait mode #define AMN_ORIENTATION_IS_PORTRAIT // Profiling Macros // Will log total time elapsed as from START_TIME to CHECK_TIME within a method. The tag must be equal. #define AMN_START_TIME(tag) #define AMN_CHECK_TIME(tag)
Debugging is great. But sometimes you need log statements to get a better sense of flow through code.
LOG_METHOD in particular get lots of usage.
These implementations not only log the value of the variable, but the name of the variable as well.
LOG_OBJECT(self.id) prints out:
2013-05-08 11:52:45.615 ExampleApp[71311:c07] self.id 3716426951 SomeController.m:91
There exist variations that are far more flexible, but I prefer being explicit about type.
// standard types #define LOG_BOOL(object) #define LOG_CHAR(object) #define LOG_INT32(object) #define LOG_UINT32(object) #define LOG_LONG(object) #define LOG_ULONG(object) #define LOG_INT64(object) #define LOG_UINT64(object) #define LOG_FLOAT(object) #define LOG_DOUBLE(object) // platform dependent #define LOG_INTEGER(object) #define LOG_UINTEGER(object) // Various Cocoa/Objective-C log macros #define LOG_OBJECT(object) #define LOG_KIND_OF_CLASS(object) #define LOG_METHOD #define LOG_END_METHOD #define LOG_METHOD_NAME #define LOG_METHOD_THREAD #define LOG_CLASS_METHOD // Various Cocoa struct log macros // NSRange #define LOG_RANGE(range) // CGPoint #define LOG_POINT(point) // CGSize #define LOG_SIZE(size) // CGRect #define LOG_RECT(rect) // CLLocationCoordinate2D #define LOG_COORD2D(coord)
Assertion macros are very good for tightening up extremely rare edge cases. You shouldn’t be using assertion as general error handling in Cocoa. In fact, you shouldn’t be using try/catch at all in most Cocoa code; it is not idiomatic. However during development, macros such as
ASSERT_NOT_NIL represent a quick, readable way to explicit about intention and also noisily alert during testing.
This particular implementation first prints out an easy to spot header, then follows up with file, line number, object info and an indispensable stack trace.
If you’d like support in the debugger, “Show Breakpoint Navigator”, click the little plus in the bottom left of the window, and then “Add Exception Breakpoint…”. The default values will then cause the debugger to pause upon encountering any assertion.
// Standard Assertions #define ASSERT_NIL(x) #define ASSERT_NOT_NIL(x) #define ASSERT_ALWAYS #define ASSERT_TRUE(test) #define ASSERT_FALSE(test) #define ASSERT_WITH_MESSAGE(x) #define ASSERT_TRUE_WITH_MESSAGE(test, msg) #define ASSERT_FALSE_WITH_MESSAGE(test, msg) // Useful, protective assertion macros #define ASSERT_IS_CLASS(x, class) #define SUBCLASSES_MUST_OVERRIDE #define SHOULD_NEVER_GET_HERE
Lastly, just a couple of utility functions that are too useful to leave out. This is kind of a junk draw to be honest.
// Unabashedly cribbed from Wil Shipley (of Delicious Monster fame) // http://www.wilshipley.com/blog/2005/10/pimp-my-code-interlude-free-code.html static inline BOOL isEmpty(id thing) // UUIDs are uuuseful. static inline CFStringRef createUniqueString(void)
Again, you can find the full source at: https://github.com/amattn/AMNGlobalUtilities/blob/master/GlobalUtilities.h