IOS自定义NSLOG和断言的使用/description方法的使用原理(对象,数组,字典)

来源:互联网 发布:小鑫优化 编辑:程序博客网 时间:2024/06/06 01:23

举例:   

 DLog(@"-----%@",@"自己添加的");


控制台输出:

 [文件名:/Users/lambo/Desktop/‰ª£Á†ÅÈõÜ/ÂÆûÁî®ÊäÄÊúØ/ÂÆûÁî®ÊäÄÊúØ11-ËßÜÈ¢ë/01-Â≠óÂÖ∏ËΩ¨Ê®°Âûã/01-Â≠óÂÖ∏ËΩ¨Ê®°Âûã/ViewController.m]

[函数名:-[ViewController viewDidLoad]]

[行号:36] 

-----自己添加的

解释:fmt实际上就是相当于@"-----%@",@"自己添加的"这一部分;
__FILE__文件名
__FUNCTION__函数名
 __LINE__行号
自己输入的参数,为fmt赋值,相当于例子中的@"-----%@",@"自己添加的";

======================
//第一种
#ifdef DEBUG
#define CLog(format, ...) NSLog(format, ## __VA_ARGS__)
#else
#define CLog(format, ...)
#endif


// 第二种 ---相当于把DLOG中的fmt 传入到 NSLog中的##__VA_ARGS__,##__VA_ARGS__吧值赋给fmt
#ifdef DEBUG
# define DLog(fmt, ...) NSLog((@"[文件名:%s]\n" "[函数名:%s]\n" "[行号:%d] \n" fmt), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define DLog(...);
#endif


参数解释:

__VA_ARGS__是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支(VC6.0的编译器不支持)。宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错, 你可以试试。

__FILE__宏在预编译时会替换成当前的源文件名

3.__LINE__宏在预编译时会替换成当前的行号

4.__FUNCTION__宏在预编译时会替换成当前的函数名称

有了以上这几个宏,特别是有了__VA_ARGS__,调试信息的输出就变得灵活多了。


#ifdef DEBUG

#define SLog(format, ...) printf("class: <%p %s:(%d) > method: %s \n%s\n", self, [[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, __PRETTY_FUNCTION__, [[NSString stringWithFormat:(format), ##__VA_ARGS__] UTF8String] )

#else

#define SLog(format, ...)

#endif



=======================断 言:
断言(assertion)是指在开发期间使用的、让程序在运行时进行自检的代码(通常是一个子程序或宏)。断言为真,则表明程序运行正常,而断言为假,则意味着它已经在代码中发现了意料之外的错误。断言对于大型的复杂程序或可靠性要求极高的程序来说尤其有用。

开发者没有必要在应用程序的每个版本中都进行断言检查,这是因为大多数项目都是有两个版本:Debug版和Release版。在Debug版中,开发者希望所有的断言都检查到,而在Release版中,往往都是禁用断言检查的。设置Release版本中禁用断言的方法如下:

在Build Settings菜单,找到Preprocessor Macros项,Preprocessor Macros项下面有一个选择,用于程序生成配置:Debug版和Release版。选择 Release项,设置NS_BLOCK_ASSERTIONS,不进行断言检查。如下图所示。





 断言 在开发中经常在使用到,先看iOS中断言的使用实例 (NSAssert)

    NSString *str = @"abcd";

    NSAssert([str isEqualToString:@"abcde"], @"str != abcde");


在断言中前面那部分输入断言条件,后面是断言条件不成立时的输出语句,上述断言的意思就是,如果字符串不等于 abcde  则输出 str != abcde

在debugt条件下程序会收到SIGABRT信号,这时候程序就会abort闪退,但是在release条件下程序能正常运行,但是不建议在正式发布程序中使用断言


关于断言的使用经常会用在判定传入的参数是不是空值,或者其他的一些需要判定的情况下




=================description方法的使用原理:
我们在使用NSLog 和 %@ 输出某个对象时,就会调用这个对象的 description 方法(这是NSLOg输出的本质),它的返回值就是 NSString 字符串类型,所以 description 默认实现返回的格式是 <类名: 对象的内存地址>,

以上输出实现的具体步骤为:
1.调用对象p的-description方法
2.拿到-description方法的返回值(NSString*)显示到屏幕上
3.-description方法默认返回的是“类名+内存地址”


那么,既然description方法的默认实现是返回类名和对象的内存地址,所以在必要情况下,我们需要重写description方法以达到改变输出结果目的,覆盖description方法的默认实现:

-(NSString *)description{

return 新的字符串;

}


注意:不要在 description 方法中同时使用 %@ 和 self,如果这样使用了,那么最终会造成程序死循环,原因是因为:如果使用了%@和self,代表要调用self的description方法,最终就是循环调用description方法,


====================字典和数组的de'scription方法:
#import "NSArray+desc.h"@implementation NSArray (desc)- (NSString *)descriptionWithLocale:(id)locale{    NSMutableString *strM = [NSMutableString stringWithString:@"(\n"];    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {        [strM appendFormat:@"\t%@,\n", obj];    }];    [strM appendString:@")"];    return strM;}@end@implementation NSDictionary (desc)- (NSString *)descriptionWithLocale:(id)locale{    NSMutableString *strM = [NSMutableString stringWithString:@"{\n"];    [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {        [strM appendFormat:@"\t%@ = %@;\n", key, obj];    }];    [strM appendString:@"}\n"];    return strM;}@end


0 0