Xcode中将环境变量当作调试开关

在开发新功能的过程中有时会为了进行一些快速的测试,会在上下文中修改变量的值或者执行一些方法来配置测试环境, 一但这么做就有可能忘记移除测试代码,将其编译到最终的发由的产品中,于是为了降低风险用#if DEBUG来包装了一下测试代码, 把风险控制在开发环境。
但是这样依然有可能干扰团队其它成员的开发。如果用宏定义开关来控制,偶尔也会因把配置文件提交而造成干扰。
那么如何做才能减少这些弊端,既能配置测试环境又不会不小心把测试代码提交到版本库呢?
想到Xcode的工程文件中的非公享Scheme是分用户的,那么里面的配置是不会扩散到团队的,可以从这里入手,看了下Xcode的Scheme配置,可以指定环境变量,在应用中就可以通过环境变量来配置测试环境,一来可以不干扰其它成员,二来也可以把一些常用的测试代码共享给别的人用。使用POSIX的getenv方法也比较方便进行标记判断,也可以带一些参数上去。
比如:

屏幕快照 2016-04-07 22.41.39


#if DEBUG
if (getenv("reset")) {
[Debugger resetApp];
}
#endif


#if DEBUG
char *tab_index = getenv("INITIAL_TAB");
if (tab_index) {
[_tabBarController setSelectedIndex:atoi(tab_index)];
}
#endif

这样就可以通过在scheme中勾选要调试的选项来进行测试了。勾选了reset,那么每次启动时就清掉所有的数据,勾选了INITIAL_TAB就会在打开App的时候自动进入对应的Tab。

除此之外如果简单的修改一些变量,可以在Xcode的断点命令中执行expr var = val这种操作,也是不会干扰到正常代码的一个方法。

lldb tips

Commands can have three forms:
Discoverable form: expression –object-description — foo
Abbreviated from  : e -O — foo
Alias: po foo

Breakpoints

b MyView.m: 4
breakpoint set –file MyView.m –line 4

b “-[MyViewA drawRect:]”
breakpoint set –name “-[MyViewA drawRect:]”

b drawRect:
breakpoint set –selector drawRect:

br co a / breakpoint command add  Breakpoint commands run each time a breakpoint is hit
> p rect expression rect
> bt thread backtrace
> c process continue
> DONE

p id $myModel = self  expression id $myModel = self // Create a presistent variable of type id
b “-[MyModel dealloc]”
br m -c “self == $myModel” breakpoint modify –condition “self == $myModel”

Watch Points 4 on Intel, 2 on ARM
w s v self->_needsSynchronization
watchpoint set variable self->_needsSynchronization

Stepping can hit breakpoints
LLDB maintains a stack of things you are doing
When you step, LLDB puts it on the stack
If you hit a breakpoint LLDB remembers the stack
So, when hit continue, LLDB will get you back to where when you hit step

Stepping repeatedly over irrelevant code gets old quickly
th u 11
thread until 11 

Call the code using Clang
b “-[ModelDerived removeDuplicates]”
e -i false — [self removeDuplicates]
expression –ignore-breakpoints false — [self removeDuplicates]

Data Formatters
Xcode 5 can show memory summary in debug area, It has builtin DataFormatters for Foundation CoreFoundation and STL
http://lldb.llvm.org/varformats.html
LLDB pass SBValue to formatter

def MyAddress_Summary(value, unused):
    firstName = value.GetChildMemberWithName("_firstName")
    lastName = value.GetChildMemberWithName("_lastName")
    firstNameSummary = firstName.GetSummary()
    lastNameSummary = lastName.GetSummary()
    return firstNameSummary + " " + lastNameSummary

ty su a MyAddress -F MyAddress_Summary

Define Types in Console
expression
typedef $NoOpaque {
int foo; int bar
}
($NoOpaque)Opaque

Custom LLDB Commands

SB stands for Script Bridge
def MyCommand_Impl(debugger, user_input, result, unused)
co sc a foo -f foo

thread = debugger.GetSelectedTarget().GetProcess().GetSelectedThread()
for frame in thread.frames:
    if frame.function.name == "MyFunction":
        # update counters
    print >>result, "depth: " + str(depth)

~/.lldbinit loaded at debugger startup
~/.lldbinit-Xcode