iOS之深入解析NSLog的调试技巧

article/2025/10/11 17:55:32

一、DEBUG 宏区分调试模式和发布模式进行特殊处理

① 利用 Configuration 配置不同的编译环境

  • 一个应用往往对应多个域名的情况,测试地址、生产地址、后台接口开发者的个人主机地址:
1.开发人员环境(Other)连接写服务人的电脑,与服务器联调使用 
2.开发环境(Debug)完成需求,代码上传,在外网开发服务器调试 
3.测试环境(Testing)测试人员使用 
4.预发布(PreRelease)测试人员使用,copy 的正式数据 
5.正式环境(Release)上传 AppStore 使用
  • 新建不同的编译环境:

在这里插入图片描述

  • 在 Build Setting 中搜索 preprocessor macro:

在这里插入图片描述

  • 定义预编译宏 Preprocessor Macros:
k_BUILD_VERSION = 0 -> 开发人员环境(Other) 
k_BUILD_VERSION = 1 -> 开发环境(Debug) 
k_BUILD_VERSION = 2 -> 测试环境(Testing) 
k_BUILD_VERSION = 3 -> 预发布环境(PreRelease) 
k_BUILD_VERSION = 4 -> 正式环境(Release)

在这里插入图片描述

  • 用预编译命令 Define 不同的 URL:
#if  (k_BUILD_VERSION == 0)// 开发人员环境(Other)your code
#elif  (k_BUILD_VERSION == 1)
// 开发环境(Debug)your code
#elif  (k_BUILD_VERSION == 2)
// 测试环境(Testing)your code
#elif  (k_BUILD_VERSION == 3)
// 预发布(PreRelease)your code
#elif  (k_BUILD_VERSION == 4)
// 正式环境(Release)your code
#endif
  • 切换 build Configuration:

在这里插入图片描述

  • 配置不同环境,如果手机装了多个环境的项目,不好区分,可以在 Xcode 配置脚本,在编译时根据不同环境制作不同的 icon 图标。

② 发布模式关闭 NSLog

// 调试模式
#ifdef DEBUG
#define NSLog(...)     NSLog(__VA_ARGS__)
#define KisDebug 1//#define NSLog(fmt, ...) NSLog((@"[文件名:%s]\n" "[函数名:%s]\n" "[行号:%d] \n" fmt), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);#else // 发布模式
#define NSLog(...)
#define KisDebug 0
#endif

二、Objective-C’s boxing capability(“装箱”快速构造数字对象)

① NSLog 的输出

  • NSLog 将消息输出到 Apple System Log 工具或 Console 应用程序:

在这里插入图片描述

② 改进 Objective-C 中的日志记录

格式说明符描述
func%s当前函数签名
LINE%d在源代码文件的当前行号
FILE%s源代码文件的完整路径
PRETTY_FUNCTION%sprint the name of the function being called
NSLog( @"calling: %s", __PRETTY_FUNCTION__ );
表达格式说明符描述
NSStringFromSelector(_cmd)%@Name of the current selector
NSStringFromClass([self class])%@Name of the current object’s class
[[NSString stringWithUTF8String:FILE] lastPathComponent]%@Name of the source code file(源代码文件的名称)
[NSThread callStackSymbols]%@NSArray of the current stack trace as programmer
 NSLog(@"%@", [NSThread callStackSymbols]);
  • 数据类型的格式说明符:
TypeFormat specifierConsiderations
NSInteger%ld or %lxCast the value to long
NSUInteger%lu or %lxCast the value to unsigned long
CGFloat%f or %g%f works for floats and doubles when formatting; but note the technique described below for scanning
CFIndex%ld or %lxThe same as NSInteger
pointer%p or %zx%p adds 0x to the beginning of the output. If you don’t want that, use %zx and no typecast

③ 装箱快速构造数字对象

  • NSLog 函数提供许多用于打印数字的替代标记(例如 %d,%ld,%f,%d 等),为了方便起见,可以使用 Objective-C 的装箱功能来节省时间并避免编译器警告:
double myNumber = 8.80;
NSLog(@"number : %@", @(myNumber));
NSLog(@"number class: %@", @(myNumber).class);// 调试结果
number : 8.8
number class: __NSCFNumber
  • 平常也可以使用 @ 来快速包装数字类型以对象的形式进行存储和传参:
    [discountArray addObject:[[self class] mj_objectWithKeyValues:@{@"placeholder":QCTLocal(@"please_input_card_num"),@"btnContent":QCTLocal(@"member_see"),@"EnterModelType":@2,@"isEnabled":@1,@"isLast":@1,@"block":block}]];

④ 打印调试(强化 NSLog)

// A better version of NSLog
#define NSLog(format, ...) do { \
fprintf(stderr, "<%s : %d> %s\n", \
[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], \
__LINE__, __func__); \
(NSLog)((format), ##__VA_ARGS__); \
fprintf(stderr, "-------\n"); \
} while (0)
  • 输出结果:
<ViewController.m : 32> -[ViewController viewDidLoad]
2022-06-26 17:33:31.022 DEUBG[12852:1238167] Hello World!
-------

三、benchmarking 的时间测量

① benchmarking

  • benchmark 是程序明确地要测量并比较硬件以及软件上的运行效率。benchmarking 表示的则是测量效率的一段代码,可结合 Instruments 进行性能分析。
  • benchmark 代码不应该被加到终极提交的产品中,Benchmarking 应该被分离到单独的项目分支或独立的测试用例中,或者使用 DEBUG 宏的区分调试模式和发布模式进行特殊处理。

② CACurrentMediaTime

  • 推荐使用包装 mach_absolute_time 的 CACurrentMediaTime() 方法来以秒为单位测量时间:
/* Returns the current CoreAnimation absolute time. This is the result of* calling mach_absolute_time () and converting the units to seconds. */CA_EXTERN CFTimeInterval CACurrentMediaTime (void)API_AVAILABLE (macos(10.5), ios(2.0));
// uint64_t                        mach_absolute_time(void);
// long timestamp = CFAbsoluteTimeGetCurrent()
  • 和 NSDate 或 CFAbsoluteTimeGetCurrent()偏移量不同的是,mach_absolute_time() 和 CACurrentMediaTime() 是基于内建时钟的,能够更精确更原子化地测量,并且不会因为外部时间变化而变化(例如时区变化、夏时制、秒突变)。
static size_t const count = 1000;       // 有多少个元素需要添加到数组
static size_t const iterations = 10000; // 测试运行的次数CFTimeInterval startTime = CACurrentMediaTime();
{for (size_t i = 0; i < iterations; i++) {@autoreleasepool {              // 循环体都被 @autoreleasepool 包裹,用来降低内存占用NSMutableArray *mutableArray = [NSMutableArray array];for (size_t j = 0; j < count; j++) {[mutableArray addObject:object];}}}
}
CFTimeInterval endTime = CACurrentMediaTime();
NSLog(@"Total Runtime: %g s", endTime - startTime);

③ dispatch_benchmark

  • dispatch_benchmark 函数返回给定块执行所需的平均纳秒数:
// 该方法并没有被公开声明,所以你必须要自己声明
extern uint64_t dispatch_benchmark(size_t count, void (^block)(void));
// 不要在 app 的提交代码中加入 benchmarking。dispatch_benchmark 可能会导致 app 被 App Store 拒绝
static size_t const count = 1000;  // 有多少个元素需要添加到数组uint64_t t = dispatch_benchmark(iterations, ^{@autoreleasepool {NSMutableArray *mutableArray = [NSMutableArray array];for (size_t i = 0; i < count; i++) { // 循环体都被 @autoreleasepool 包裹,用来降低内存占用[mutableArray addObject:object];}}
});
NSLog(@"[[NSMutableArray array] addObject:] Avg. Runtime: %llu ns", t);

http://chatgpt.dhexx.cn/article/FPcY40Pr.shtml

相关文章

TDD(测试驱动开发)死了吗?

01、前言 很早之前&#xff0c;曾在网络上见到过 TDD 这 3 个大写的英文字母&#xff0c;它是 Test Driven Development 这三个单词的缩写&#xff0c;也就是“测试驱动开发”的意思——听起来很不错的一种理念。 其理念主要是确保两件事&#xff1a; 确保所有的需求都能被照…

unitTest+Ddt数据驱动测试

我们设计测试用例时&#xff0c;会出现测试步骤一样&#xff0c;只是其中的测试数据有变化的情况&#xff0c;比如测试登录时的账号密码。这个时候&#xff0c;如果我们依然使用一条case一个方法的话&#xff0c;会出现大量的代码冗余&#xff0c;而且效率也会大大降低。此时&a…

测试驱动开发(TDD)的理论基础

在开始理论介绍之前&#xff0c;先思考一个问题&#xff1a;软件开发中最重要的是什么&#xff1f; 可能有的小伙伴就会说&#xff1a;良好的数据库设计&#xff0c;一个健壮可扩展的架构&#xff0c;规范的编码风格&#xff0c;设计文档等。没错这些在开发中都很重要&#xf…

什么时候应该编写单元测试?什么是TDD?

一、传统方法与TDD方法 1、有人认为软件编码完成后编写单元测试&#xff08;传统方法&#xff09;&#xff0c;流程如下&#xff1a; 缺点&#xff1a;编写完功能代码再写单元测试会导致单元测试“粒度”比较粗。对同样的功能代码&#xff0c;如果采用TDD方案&#xff0c;结果…

前端做自动化测试 —— 用TDD的思想做组件测试

Test-Driven Development(测试驱动开发,以下简述TDD)是一种设计方法论, 原理是在开发功能代码之前, 先编写单元测试用例代码, 通过测试来推动整个开发的进行. 本文详细描述了在创作 react-stillness-component, 组件的过程中, 是如何学习 TDD 的思想来完成功能开发以及测试的 一…

深度解读 - TDD(测试驱动开发)

本文结构&#xff1a; 什么是 TDD为什么要 TDD怎么 TDDFAQ学习路径延伸阅读 什么是 TDD TDD 有广义和狭义之分&#xff0c;常说的是狭义的 TDD&#xff0c;也就是 UTDD&#xff08;Unit Test Driven Development&#xff09;。广义的 TDD 是 ATDD&#xff08;Acceptance Tes…

【TDD】测试驱动开发

欢迎关注微信公众号“Python小灶&#xff0c;和我一起每天学习Python新知识”&#xff0c;还可添加博主Vx&#xff1a;yf03064131&#xff0c;方便一起交流学习。 或者B站搜索 有只小新 原视频地址链接&#xff1a;点击这里 代码地址&#xff1a;点击这里 本文为大致翻译以及…

测试驱动开发(TDD)的学习使用

测试驱动开发TDD 是一种不同于传统软件开发流程的新型开发方式 特点&#xff1a; 先编写测试代码 – 实现主要逻辑 再写功能代码 – 实现细节 通过测试来推动整个开发的进行。 有助于编写简洁可用和高质量的代码&#xff0c;并加速开发过程呢。 比如写一个Person类&#xff0c;…

从 TDD 到测试策略

“ 前端没法 TDD / 前端不容易做 TDD / 前端 TDD 收益不大 ” 这是进公司后无数人给我判的“死刑”。 事实上好像的确如此&#xff1f; 在这个崇尚敏捷的组织里&#xff0c;我们有毕业生的入职前培训&#xff0c;入职后培训&#xff0c;有 TwU&#xff0c;有无数定期不定期的…

使用ddt执行数据驱动测试

所谓数据驱动测试&#xff0c;简单的理解为数据的改变从而驱动自动化测试的执行&#xff0c;最终引起测试结果的改变。通过使用数据驱动测试的方法&#xff0c;可以在需要验证多组数据测试场景中&#xff0c;使用外部数据源实现对输入输出与期望值的参数化&#xff0c;避免在测…

先测试再开发?TDD测试驱动开发了解一下?

1、什么是TDD 我第一次接触TDD这个概念&#xff0c;是在<<代码整洁之道>>中&#xff0c;作者鲍勃大叔在书中&#xff0c;写了一些关于测试代码的代码规范&#xff0c;其实就提到了有关TDD三定律: - 定律一&#xff1a; 在编写不能通过的单元测试前&#xff0c;不…

测试驱动开发(TDD)前端篇

当你在写生产代码时&#xff0c;你处在高认知的状态&#xff08;obvious&#xff09;&#xff0c;你的研发流程和你的工程实践&#xff0c;有助于你一步一步的提升你的认知能力&#xff0c;把你的问题进行一个降解&#xff08;分解&#xff09;&#xff0c;只要你做到同样的事情…

TDD 开发测试

测试驱动开发(Test-Driven Development)。是敏捷开发中的一项核心实践和技术。 TDD是在开发功能代码之前&#xff0c;先编写单元测试用例代码&#xff0c;测试代码确定需要编写什么产品代码。 变红 ——> 变绿 ——> 重构 在进行 TDD 案例编写的时候&#xff0c;看一…

TDD测试驱动开发

TDD测试驱动开发 什么是测试驱动开发测试驱动开发该怎么做&#xff1f;需求一&#xff1a;输入一个非元音字符&#xff0c;并预期返回字符本身 (输入"h" 返回“h”)需求二&#xff1a;输入一个元音&#xff08;a,e,i,o,u&#xff09;&#xff0c;返回 mommy (输入&qu…

TDD测试驱动学习

gtest 和 gmock 安装 //如果不知道对应库名字可以执行这个命令查找对应库,如果没找到要去跟新对应的源sudo apt update sudo apt-cache search gtest sudo apt-cache search gmock 测试例子 #include <string> using std::string;// 定义 Soundex 类 class Soundex {pub…

TDD (test driver development)测试驱动开发

##为什么需要测试驱动/或者说需要单元测试 我们工作接触的软件项目&#xff0c;不是学生时代&#xff0c;玩一玩就不管了&#xff0c;工作的项目&#xff0c;需要长期维护&#xff0c;并且随着时间的推移需要增加新的需求&#xff0c;进行修改&#xff0c;优化。此时已经距离你…

tdd(测试驱动开发)的概述

最近的工作的项目&#xff0c;使用了tdd&#xff08;test-driven development测试驱动开发&#xff09;的开发模式。 这两几年大概听说了无数种xxx-dd, ddd, tdd, atdd, bdd, fdd, udd各种名词眼花缭乱&#xff0c;当然很多dd其实也有相互借鉴&#xff08;抄袭&#xff09;的部…

测试驱动开发(TDD)实践与技巧

文章目录 引言Google Mock测试用例结构断言经典式断言Hamcrest 断言 测试驱动开发&#xff1a;第一个示例开场白开始吧去掉不干净的代码增量性fixture 设置思索与测试驱动开发测试驱动与测试 测试驱动开发基础与单元测试单元测试的组织结构测试驱动开发周期&#xff1a;红-绿-重…

opencv配置相关的截图参考

opencv配置相关的截图参考&#xff0c;如下&#xff1a;

Anaconda3安装及opencv配置

一、Anaconda安装 1.直接百度搜anaconda&#xff0c;进入官网即可&#xff08;anaconda网站链接&#xff09; 2.点击图片上黑框&#xff08;Get Started&#xff09;即可进入下一步&#xff0c;选择下图中第四个 3.选择适合电脑类型的anaconda安装器&#xff0c;注意选好64位…