一、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)
# if ( k_BUILD_VERSION == 0 )
your code
# elif ( k_BUILD_VERSION == 1 )
your code
# elif ( k_BUILD_VERSION == 2 )
your code
# elif ( k_BUILD_VERSION == 3 )
your code
# elif ( k_BUILD_VERSION == 4 )
your code
# endif
配置不同环境,如果手机装了多个环境的项目,不好区分,可以在 Xcode 配置脚本,在编译时根据不同环境制作不同的 icon 图标。
② 发布模式关闭 NSLog
# ifdef DEBUG
# define NSLog ( . . . ) NSLog ( __VA_ARGS__)
# define KisDebug 1
# 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 %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 callStackSymbols] ) ;
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
③ 装箱快速构造数字对象
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)
# 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() 方法来以秒为单位测量时间:
CA_EXTERN CFTimeInterval CACurrentMediaTime ( void )
API_AVAILABLE ( macos ( 10.5 ) , ios ( 2.0 ) ) ;
和 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 {
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 ) ) ;
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++ ) {
[ mutableArray addObject: object] ;
}
}
} ) ;
NSLog ( @"[[NSMutableArray array] addObject:] Avg. Runtime: %llu ns" , t) ;