0
点赞
收藏
分享

微信扫一扫

iOS小技能:NSLog调试技巧


前言

  1. DEBUG 宏区分调试模式和发布模式进行特殊处理
  2. Objective-C's boxing capability (​​装箱​​快速构造数字对象)
  3. benchmarking的时间测量

I 自定义preprocessor macro

DEBUG 宏的应用场景:区分调试模式和发布模式进行特殊处理

  • 自定义preprocessor macro:

The DEBUG preprocessor macro setting in an Xcode project

iOS小技能:NSLog调试技巧_测试环境

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

应用场景: 一个应用对应多个域名的情况,测试地址、生产地址、后台接口开发者的个人主机地址

1.开发人员环境 (Other)

连接写服务人的电脑,与服务器联调使用 2.开发环境(Debug) 完成需求,代码上传,在外网开发服务器调试 3.测试环境 (Testing) 测试人员使用 4.预发布 (PreRelease) 测试人员使用,copy的正式数据 5.正式环境 (Release) 上传AppStore使用

  • 新建不同的编译环境


  • 定义预编译宏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)

iOS小技能:NSLog调试技巧_objective-c_02

  • 用预编译命令Define不同的URL

#if
//开发人员环境 (Other)
your code
#elif
//开发环境(Debug)
your code
#elif
//测试环境 (Testing)
your code
#elif
//预发布 (PreRelease)
your code
#elif
//正式环境 (Release)
your code
#endif

  • 切换 build Configuration


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

1.2 发布模式关闭NSLog

//调试模式
#ifdef
#define
#define

//#define NSLog(fmt, ...) NSLog((@"[文件名:%s]\n" "[函数名:%s]\n" "[行号:%d] \n" fmt), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);

#else//发布模式
#define
#define
#endif

II NSLog调试技巧

2.1 Where to find NSLog's output

NSLog outputs messages to the Apple System Log facility or to the Console app

iOS小技能:NSLog调试技巧_objective-c_03

2.2 Improved logging in Objective-C

  • ​​Improved logging in Objective-C​​


格式说明符

描述

func

%s

当前函数签名

LINE

%d

在源代码文件的当前行号

FILE

%s

源代码文件的完整路径

PRETTY_FUNCTION

%s

print 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

iOS小技能:NSLog调试技巧_iOS_04

  • Format specifiers for data types

Type

Format specifier

Considerations

​NSInteger​

​%ld​​​ or ​​%lx​

Cast the value to ​​long​​.

​NSUInteger​

​%lu​​​ or ​​%lx​

Cast 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 ​​%lx​

The 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.

2.3 Objective-C's boxing capability (装箱快速构造数字对象)

The printf function ​​NSLog​​ offers a number of substitution tokens for printing numbers (%d, %ld, %f, %d, for example). As a convenience, you can use Objective-C's boxing capability to save time and avoid compiler warnings.

  • For example

iOS小技能:NSLog调试技巧_#define_05

平常也可以使用​​@​​ 来快速包装数字类型以对象的形式进行存储和传参

iOS小技能:NSLog调试技巧_objective-c_06

self class] mj_objectWithKeyValues:@{@"placeholder":QCTLocal(@"please_input_card_num"),@"btnContent":QCTLocal(@"member_see"),@"EnterModelType":@2,@"isEnabled":@1,@"isLast":@1,@"block":block}]];

2.4 打印调试(强化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]
2016-10-14 17:33:31.022 DEUBG[12852:1238167] Hello World!
-------

2.5 知识补充:装箱和拆箱

​​blog.csdn.net/z929118967/…​​

III benchmarking的时间测量

benchmark 是程序明确地要测量并比较硬件以及软件上的运行效率。

benchmarking 表示的则是测量效率的一段代码,可结合Instruments进行性能分析。

提出问题->->构造假说->预期结果->验证假说(​​在真实设备上 benchmark​​)->分析结果

benchmark 代码不应该被加到终极提交的产品中,Benchmarking 应该被分离到单独的项目分支或独立的测试用例中,或者使用DEBUG 宏的区分调试模式和发布模式进行特殊处理。

例子:向可变数组中添加元素的效率,验证​​ NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:count];​​​ 的效率是否比​​[NSMutableArray array]​​更快?

3.1 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);

3.2 dispatch_benchmark

The dispatch_benchmark function returns the average number of nanoseconds the given block takes to execute.

//这个方法并没有被公开声明,所以你必须要自己声明
extern uint64_t dispatch_benchmark(size_t count, void (^block)(void));
//不要在你 app 的提交代码中加入 benchmarking。 dispatch_benchmark 可能会导致 app 被 App Store 拒绝,

​​opensource.apple.com/source/libd…​​

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);

IV demo

本文demo从​​小程序:iOS逆向​​​内搜​​NSLog​​获取

举报

相关推荐

0 条评论