IOS知识积累

XCode启动参数和环境变量配置

2019-10-12  本文已影响0人  司空123

当我们使用Xcode调试app的时候,会传递一些额外的参数进去,覆盖系统的默认值,从而实现特定场景的调试。主要手段就是配置启动参数和环境变量.
全部的配置分布在Info Arguments options Diagnostics四个板块中

一 首先Info板块:

  1. build configuration :构建运行模式
设置运行模式`Debug`还是`Release`
也可以自定义构建环境,但依然区分`Debug`还是`Release`
  1. debug process as: 调试角色
是当前用户发起的调试行为还是root行为
  1. launch :启动时机
`Automatically`:自动启动运行
`Wait for executable to be launched` : app处于等待状态,当点击图标或者收到push notification才会启动。
用于调试app启动前的逻辑

二 首先Arguments板块: 启动参数&环境变量

启动参数:Argument Passed On Launch :

配置启动参数 用来覆盖NSUserDefaults中的默认值。启动参数只有在通过XCode启动App的时候才会起作用,直接点击图标启动是没用的

1.AppleLanguages可以用来设置启动的语言
更改语言最直接的方式就是:设置 -> 通用 -> 语言 -> 修改语言,然后重启模拟器,接着重启App,这个过程是很繁琐的。

利用启动参数,这个过程变得非常的直接,比如,设置App在简体中文下启动

-AppleLanguages (zh-Hans)
一些常见的语言列表如下:

English (U.S.)              en
English (UK)                en-GB
English (Australian)        en-AU
English (Indian)            en-IN
French                      fr
Spanish                     es
Portuguese                  pt
German                      de
Italian                     it
Chinese (Simplified)        zh-Hans
Chinese (Traditional)       zh-Hant
Japanese                    ja
Korean                      ko
Russian                     ru

2.实现本地化

当你的App需要同时支持多语言的时候,本地化变得很重要。同样的文字,可能在某一中语言中会显示的很长,这时候你可以先通过NSDoubleLocalizedStrings来看看你的UI在双倍显示当前字符串的时候的样子:

-NSDoubleLocalizedStrings YES

检查哪些字符串没有被本地化

-NSShowNonLocalizedStrings YES

开启这个参数,运行项目,对于没有本地话的字符串,会打印出log,并且在英文环境下,没有被本地话的字符串会变成全部是大写的:

  1. 输出Core Data跟踪日志

当你使用Core Data作为本地持久化存储的技术栈时,你会发现很难对程序进行跟踪,这时候可以使用启动参数

-com.apple.CoreData.SQLDebug 3

log等级分为1到3,越高越详细

4.Core Data迁移调试

-com.apple.CoreData.MigrationDebug
  1. 日志语法高亮
    想让调试语句更加突出吗? 可以使用如下的颜色混合日志参数
-com.apple.CoreData.SyntaxColoredLogging YES

屏幕快照 2019-10-12 下午4.56.12.png
环境变量: Environment Variable

通过代码获取环境变量

[[NSProcessInfo processInfo] environment]
  1. DYLD : 优化过App启动时间的同学都知道,启动时间分为main前和main后,XCode可以通过环境变量来打印main函数前的几个过程.

常用的有两个环境变量:

DYLD_PRINT_STATISTICS
DYLD_PRINT_STATISTICS_DETAILS
屏幕快照 2019-10-12 下午5.03.53.png

再运行应用,会发现log打印,然后你就知道哪里拖慢了你的应用启动:

         dylib loading time:  26.31 milliseconds (26.5%)
        rebase/binding time:   1.03 milliseconds (1.0%)
            ObjC setup time:  10.59 milliseconds (10.6%)
           initializer time:  61.15 milliseconds (61.6%)
           slowest intializers :
             libSystem.B.dylib :   5.57 milliseconds (5.6%)
   libBacktraceRecording.dylib :   3.18 milliseconds (3.2%)
    libMainThreadChecker.dylib :  30.87 milliseconds (31.1%)
                         ZBank :  34.67 milliseconds (34.9%)

  total time: 1.0 seconds (100.0%)
  total images loaded:  372 (365 from dyld shared cache)
  total segments mapped: 20, into 449 pages with 48 pages pre-fetched
  total images loading time: 747.41 milliseconds (73.6%)
  total load time in ObjC:  10.59 milliseconds (1.0%)
  total debugger pause time: 721.09 milliseconds (71.0%)
  total dtrace DOF registration time:   0.10 milliseconds (0.0%)
  total rebase fixups:  373,831
  total rebase fixups time:   9.04 milliseconds (0.8%)
  total binding fixups: 544,195
  total binding fixups time: 186.19 milliseconds (18.3%)
  total weak binding fixups time:   0.76 milliseconds (0.0%)
  total redo shared cached bindings time: 194.97 milliseconds (19.2%)
  total bindings lazily fixed up: 0 of 0
  total time in initializers and ObjC +load:  61.15 milliseconds (6.0%)
                         libSystem.B.dylib :   5.57 milliseconds (0.5%)
               libBacktraceRecording.dylib :   3.18 milliseconds (0.3%)
                libMainThreadChecker.dylib :  30.87 milliseconds (3.0%)
                                     ZBank :  34.67 milliseconds (3.4%)
total symbol trie searches:    1239212
total symbol table binary searches:    0
total images defining weak symbols:  37
total images using weak symbols:  100

除此之外,dyld还有很多可以用来调试的环境变量

DYLD_FRAMEWORK_PATH
DYLD_FALLBACK_FRAMEWORK_PATH
DYLD_VERSIONED_FRAMEWORK_PATH
DYLD_LIBRARY_PATH
DYLD_FALLBACK_LIBRARY_PATH
DYLD_VERSIONED_LIBRARY_PATH
DYLD_PRINT_TO_FILE
DYLD_SHARED_REGION
DYLD_INSERT_LIBRARIES
DYLD_FORCE_FLAT_NAMESPACE
DYLD_IMAGE_SUFFIX
DYLD_PRINT_OPTS
DYLD_PRINT_ENV
DYLD_PRINT_LIBRARIES
DYLD_BIND_AT_LAUNCH
DYLD_DISABLE_DOFS
DYLD_PRINT_APIS
DYLD_PRINT_BINDINGS
DYLD_PRINT_INITIALIZERS
DYLD_PRINT_REBASINGS
DYLD_PRINT_SEGMENTS
DYLD_PRINT_STATISTICS
DYLD_PRINT_DOFS
DYLD_PRINT_RPATHS
DYLD_SHARED_CACHE_DIR
DYLD_SHARED_CACHE_DONT_VALIDATE
  1. Zombie:

开启Zombie,当对象被释放后,他们仍然在内存里,只不过视图访问僵尸对象会报错,可以用于调试EXC_BAD_ACCESS。
可以通过环境变量NSZombieEnabled来开启

NSZombieEnabled YES

也可以选择NSDeallocateZombies,这样僵尸对象的内存会被释放调。

NSDeallocateZombies YES
屏幕快照 2019-10-12 下午5.25.27.png
  1. MallocDebug

内存相关的bug是很难调试的,幸运的是XCode为我们提供了一系列工具,这组工具就是malloc debug。
环境变量对应的功能如下:

20180630125224801.png

MallocStackLogging

记录下来内存分配的调用栈,配合memory debugging等其他可以获取到对象内存地址的debug技巧,可以很容易的查看到一个对象是如何被创建的

MallocScribble

对于释放的内存,每个Byte填充成0x55,能够提高野指针的crash率。

原理:
以OC对象为例,对象被释放后,内存被标记为回收,
但是在第二次写入前,内存还是之前的OC对象;
这就导致了即使对象被释放了,
只有内存被覆盖后的野指针访问才会crash。

对于开发者来说:野指针的crash很有可能是在对象被释放一段时间后,给调试带来了难度,而MallocScribble会在内存释放后,强制覆盖内存,提高野指针的crash率。

MallocGuardEdges
在分配大内存的时候,在内存前后添加额外的页,进行内存保护。

MallocGuard
开启Malloc Guard后,在调试的时候会使用libgmalloc替换malloc,从而在当内存出现错误的时候,及时crash你的App。
可以通过以下环境变量来开启MallocGuard:

DYLD_INSERT_LIBRARIES /usr/lib/libgmalloc.dylib

在不开启malloc guard的时候,会crash在main函数,并不会提供有用的信息,在开启malloc guard后:

20180630125300902.png

4.自定义环境变量

除了系统的启动参数和环境变量之外,也支持自定义参数。

我们都知道NSUserDefaults可以用来存储用户的配置信息,比如有一个配置信息是AllowCellularNetwork,即是否允许蜂窝移动网络下访问网络,这时候就可以测试在用户不同设置的情况下启动:


20180630125317414.png

当开发一个framework的时候,可以利用环境变量来开启一些debug功能,这样能保证线上环境不受影响。


20180630125336145.png

然后,在代码里读取

NSDictionary * environments = [[NSProcessInfo processInfo] environment];
BOOL logOn = [[environments objectForKey:@"Network_Log_Enabled"] isEqualToString:@"YES"];

options板块:

Core Location用来模拟App的位置
Application Data 可以用于测试CoreData的Scheme迁移
Routing App Coverage File 一个GeoJSON文件,对于导航类应用指明App支持的区域
GPU Frame Capture GPU帧率检测
Background fetch 表示启动由backgroud fetch触发
Show non-localized strings 显示没有本地话的字符串
Application Language & Application Region 系统的语言和区域
options 中的部分配置可以通过配置环境变量来实现

四. Diagnostics (诊断)板块:

1.Runtime Sanitization运行时调试选项:
启用运行时检查以检测并避免代码中的错误。
Enable Address Sanitizer

// 跟踪代码中的内存冲突。

Thread Sanitization

审核代码中的线程问题。

undefined behavior sanitizer 可在运行时检测未定义的行为

undefined behavior sanitizer可以在运行时检查未定义的行为。
对性能的影响很小,在Debug配置中平均有20%的CPU开销。
未定义的行为包括:整数溢出,无效的布尔枚举值,被零除等
  1. Runtime API Checking 运行时API检查

Main Thread Checker 主线程检查
当使用Xcode调试器运行应用程序时,主线程检查器将自动启用。

从后台线程检测对AppKit,UIKit和其他API的无效使用。
  1. Memory Management内存管理
    同环境变量配置的内容交叉,在这里可以更加直观的配置.
    开启一些内存管理相关的服务,包括内存涂抹,边缘保护,动态内存分配保护,僵尸对象等等
Malloc Scribble          // 内存涂抹 用0xAA填充分配的内存,用0x55填充释放的内存。

Malloc Guard Edges       // 内存边缘保护
Guard Malloc             // 动态内存分配保护
Zombie Objects           // 僵尸对象

Malloc Scribble的基本思想是,在对象被释放后,在对应内存块中填上不可访问的无意义的数据(0x55),那么我们再使用这个对象时,程序将直接Crash

  1. Logging后台日志

malloc stack // malloc堆栈日志
Dynamic Linker API Usage // 记录动态链接器API调用(例如,dlopen)。
Dynamic Linker Loads // 记录加载的动态库

参考链接:https://blog.csdn.net/Hello_Hwc/article/details/80865787

上一篇下一篇

猜你喜欢

热点阅读