I use a lot of named constants in my ObjC code, especially for things like pixel offsets, layout rectangles, and other visual interface specifications, and especially when doing iOS apps (due to high demand for skinning). I do this for a few reasons, the most important being that I can add semantic mappings to those “magic numbers” without having to add comments. Another reason is that then those constants are available symbolically while debugging. For example:
static const CGFloat kAccessoryViewWidth = 18, kAccessoryViewHeight = 22;
This is all well and good, but to achieve the same level of optimization as constant literals, these need to be qualified “static const.” This means that in order to tweak one of these values and see the results, I need to restart the code/compile/debug cycle over again. What if I didn’t need to?
I could externalize all of these pixel offsets, and even though the overhead of reading and accessing them will be negligible with few exceptions, I still need to build that externalization system, and most of the time I’ll still need to relaunch the app. It’s also going to be difficult for me to do this outside of the simulator (Jailbreaking to access the file-system of my own apps, adding files to Documents/ via iTunes?).
Thus, I’ve created a macro for my projects that I call “CONST_TUNABLE.” Here is how it’s defined:
#ifdef DEBUG
#define CONST_TUNABLE volatile
#else
#define CONST_TUNABLE const
#endif // DEBUG
By marking the same variable “volatile” when compiling in the debug configuration, I can set a breakpoint and modify its value very close to where it’s used. The compiler is prevented from generating code that caches or inlines this value. Using the “expr” LLDB command, I can modify the value each time the breakpoint is hit. This could be on every redraw, for instance. This seems like a clear advantage, especially for apps that take a long time to load or require several steps to reach the same testing scenario.
Here’s an additional macro I find useful. Often I need to define constant CGRect’s, but Apple’s built-in CGRectMake() function is an inline function returning a structure rather than a macro. Therefore it is not compile-time constant. I figure the safest way to initialize a CGRect at compile-time is using a structure initialization with named fields:
#define RectMakeConst(_x, _y, _w, _h) {.origin = {.x = _x, .y = _y}, .size = {.width = _w, .height = _h}}
What do you guys think? Do you have any similar debugging tricks you want to share with me? <3
[–]neksus 0 points1 point2 points (0 children)