内容简介:最近在写《iOS代码调试》系列的博客,估计会有十篇以上的内容,等到都写完了会在Github以一个仓库的形式开源出来,欢迎关注我的Github:LeoMobileDeveloper这一部分介绍XCode中Argument/Options模块,通过这两个模块,我们可以在启动App的时候传递一些额外的参数进去,覆盖系统的默认值,从而实现特定场景的调试。
前言
最近在写《iOS代码调试》系列的博客,估计会有十篇以上的内容,等到都写完了会在Github以一个仓库的形式开源出来,欢迎关注我的Github:
LeoMobileDeveloper
这一部分介绍XCode中Argument/Options模块,通过这两个模块,我们可以在启动App的时候传递一些额外的参数进去,覆盖系统的默认值,从而实现特定场景的调试。
Options
Options这里的内容相对简单,但是却容易被忽略。
Core Location用来模拟App的位置
Application Data 可以用于测试CoreData的Scheme迁移
Routing App Coverage File 一个GeoJSON文件,对于导航类应用指明App支持的区域
Background fetch 表示启动由backgroud fetch触发
Show non-localized strings 显示没有本地话的字符串
Application Language & Application Region 系统的语言和区域
Argument Passed On Launch
启动参数用来覆盖NSUserDefaults中的默认值。
注意 :启动参数只有在通过XCode启动App的时候才会起作用,直接点击图标启动是没用的。
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
当然,也可以通过Options中的图形化界面来设置语言:
本地化
当你的App需要同时支持多语言的时候,本地化变得很重要。同样的文字,可能在某一中语言中会显示的很长,这时候你可以先通过 NSDoubleLocalizedStrings
来看看你的UI在双倍显示当前字符串的时候的样子:
-NSDoubleLocalizedStrings YES
对比下开启前后的效果
当你完成了本地化,你想知道那些字符串没有被本地化
-NSShowNonLocalizedStrings YES
开启这个参数,运行项目,对于没有本地话的字符串,会打印出log,并且在英文环境下,没有被本地话的字符串会变成全部是大写的:
2018-06-09 17:16:23.899756+0800 LaunchArgumentDemo[1592:42786] [strings] ERROR: FlZ-Ch-fUI.text not found in table Main of bundle CFBundle 0x7ffd464002e0 …/Bundle/Application/43466A60-F706-4CCE-A3D5-064C05CD04C6/LaunchArgumentDemo.app> (executable, loaded)
这里有个小技巧,如果是xib/storyboard中的视图,需要通过源代码查看的方式去找到问题: 右键Storyboard -> Open As -> Source Code。接着查找log中提到的id:
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Leo'Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FlZ-Ch-fUI"> <rect key="frame" x="278" y="626.5" width="77" height="20.5"/> <fontDescription key="fontDescription" type="system" pointSize="17"/> <nil key="textColor"/> <nil key="highlightedColor"/> label>
Core Data
当你使用Core Data作为本地持久化存储的技术栈时,你会发现很难对程序进行跟踪,这时候可以使用启动参数
log等级分为1到3,越高越详细
-com.apple.CoreData.SQLDebug 3
Log如下
CoreData: sql: pragma cache_size=1000 CoreData: sql: SELECT ...
还有Core Data迁移调试
-com.apple.CoreData.MigrationDebug
Environment Variable
对比启动参数,环境变量的作用域更广一些,它更像是App的全局变量,在应用内任何地方都可以访问到。
可以通过以下方式在代码里获取环境变量
[[NSProcessInfo processInfo] environment]
dyld
优化过App启动时间的同学都知道,启动时间分为main前和main后,XCode可以通过环境变量来打印main函数前的几个过程
-
这部分如果不了解,可以参考我之前的这篇文章《 深入理解App的启动过程 》
常用的有两个环境变量
DYLD_PRINT_STATISTICS DYLD_PRINT_STATISTICS_DETAILS
比如,开启 DYLD_PRINT_STATISTICS
,
再运行应用,会发现log打印,然后你就知道哪里拖慢了你的应用启动:
Total pre-main time: 823.29 milliseconds (100.0%) dylib loading time: 226.83 milliseconds (27.5%) rebase/binding time: 391.41 milliseconds (47.5%) ObjC setup time: 72.95 milliseconds (8.8%) initializer time: 131.81 milliseconds (16.0%) slowest intializers : libSystem.dylib : 12.17 milliseconds (1.4%) Foundation : 45.39 milliseconds (5.5%) libMainThreadChecker.dylib : 74.21 milliseconds (9.0%)
除此之外,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
Zombie
开启Zombie,当对象被释放后,他们仍然在内存里,只不过视图访问僵尸对象会报错,可以用于调试 EXC_BAD_ACCESS
。
可以通过环境变量NSZombieEnabled来开启
NSZombieEnabled YES
也可以选择NSDeallocateZombies,这样僵尸对象的内存会被释放调。
MallocDebug
内存相关的bug是很难调试的,幸运的是XCode为我们提供了一系列工具,这组 工具 就是malloc debug。
环境变量对应的功能如下:
MallocStackLogging
记录下来内存分配的调用栈,配合memory debugging等其他可以获取到对象内存地址的debug技巧,可以很容易的查看到一个对象是如何被创建的
MallocStackLoggingNoCompact的log粒度比MallocStackLogging更细一些,功能上类似
MallocScribble
对于释放的内存,每个Byte填充成0x55,能够提高野指针的crash率。
原理:以OC对象为例,对象被释放后,内存被标记为回收,但是在第二次写入前,内存还是之前的OC对象;这就导致了即使对象被释放了,只有内存被覆盖后的野指针访问才会crash。
对于开发者来说:野指针的crash很有可能是在对象被释放一段时间后,给调试带来了难度,而MallocScribble会在内存释放后,强制覆盖内存,提高野指针的crash率。
MallocGuardEdges
在分配大内存的时候,在内存前后添加额外的页,进行内存保护。
这个环境变量用处比较少,起码我写了这么久的代码,还没有遇到过MallocGuardEdges帮我找到的内存问题。
MallocGuard
开启Malloc Guard后,在调试的时候会使用libgmalloc替换malloc,从而在当内存出现错误的时候,及时crash你的App。
可以通过以下环境变量来开启MallocGuard
DYLD_INSERT_LIBRARIES /usr/lib/libgmalloc.dylib
举例:
int * array = malloc(sizeof(int) * 10); for (int index = 0; index < 20; index ++) { array[index] = index; }
在不开启malloc guard的时候,会crash在main函数,并不会提供有用的信息,在开启malloc guard后:
自定义
除了系统的启动参数和环境变量之外,也支持自定义参数。
我们都知道NSUserDefaults可以用来存储用户的配置信息,比如有一个配置信息是 AllowCellularNetwork
,即是否允许蜂窝移动网络下访问网络,这时候就可以测试在用户不同设置的情况下启动:
当开发一个framework的时候,可以利用环境变量来开启一些debug功能,这样能保证线上环境不受影响。
然后,在代码里读取
NSDictionary * environments = [[NSProcessInfo processInfo] environment]; BOOL logOn = [[environments objectForKey:@"Network_Log_Enabled"] isEqualToString:@"YES"];
资料
---------------------
作者:黄文臣
原文:https://blog.csdn.net/Hello_Hwc/article/details/80865787
以上所述就是小编给大家介绍的《XCode启动参数和环境变量》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- PXC状态参数与变量参数
- react - 3.页面变量的渲染和传递参数
- Shell编程—【04】函数的定义、参数、变量作用域、函数库
- 应用诊断利器Arthas ByteKit 深度解读(2):本地变量及参数绑定
- 全局变量,静态全局变量,局部变量,静态局部变量
- python变量与变量作用域
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。