记录开发过程中遇到的小知识点。
JDNetLog(s,...)引发的问题
在做自己的项目的时候,一遍都会重新定义NSLog宏,方便在发布的时候将打印的log去除。这里就不多少了,首先贴上代码
#define JDNetLog(s, ...) [[JDiPadNetworkingLog sharedNetworkingLog] file:__FILE__ function: (char *)__FUNCTION__ \
lineNumber:__LINE__ format:(s),##__VA_ARGS__]
- (void)file:(char*)sourceFile function:(char*)functionName lineNumber:(int)lineNumber format:(NSString*)format, ...
{
va_list ap;
NSString *print, *file, *function;
// NSMutableString *mStr = [NSMutableString string];
va_start(ap,format);
file = [[NSString alloc] initWithBytes:sourceFile length:strlen(sourceFile) encoding:NSUTF8StringEncoding];
function = [NSString stringWithCString: functionName encoding:NSUTF8StringEncoding];
// if (format) {
// do {
// [mStr appendString:[NSString stringWithFormat:@"%@",format]];
// format = va_arg(ap, id);
// } while (format);
// }
//问题的根源就是没有理解这个函数!
print = [[NSString alloc] initWithFormat:format arguments:ap];
// print = [mStr copy];
va_end(ap);
if (!_dateformatter) {
_dateformatter=[[NSDateFormatter alloc] init];
[_dateformatter setDateStyle:NSDateFormatterShortStyle];
[_dateformatter setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"];
}
NSString *date = [_dateformatter stringFromDate:[NSDate date]];
[self addLog:[NSString stringWithFormat:@"\n[%@]\n%@:%d\n%@;\n%@\n",date ,[file lastPathComponent], lineNumber, function, print]];
}
首先说一下 ... 这个函数,在iOS里面,这个表示的是可变的参数类型,也就是不定参数个数。处理的方法是用C语言的语法va_list, va_start, va_end,va_arg(ap,type) 首先声明一个 va_list ,使用 va_start 方法初始化这个 va_list ,也就是传入第一个参数的指针进行初始化,va_arg就是来将指针指向下一个参数,这样就可以根据链条一直找到最后一个参数,最后就 va_end 就结束了。这里主要是对 print = [[NSString alloc] initWithFormat:format arguments:ap]; 函数理解错误了,看到这个函数传的是首指针的地址和 va_list ,之前自以为是以为是将之后传的所有参数都与前面拼接之后生成一个字符串,其实并不是这样,这个方法与 [NSString stringWithFormat:@"%@",format] 类似,只是将前面的format与arguments分开了而已,也是要遵循 @"%@%@",argument1, argument2 这样的格式,所以函数里传入的 va_list 只是符合这个格式 arguments ,并不是我们传递进去的 va_list。所以在使用 JDNetLog(s,...) 时要注意传入的格式。
关于面向接口编程
今天完成了任务之后,突然想到了在书上看到的面向接口编程,而不是面向对象编程,也是困惑了一段时间(尼玛,老子在学校学的都是面向对象,你现在有不用了?)。今天大概了解了一下,其实并不是要抛弃面向对象的思想,而是减少对象依赖。简单的说就是不要在其他类中直接使用对象的属性,而是包装一层在接口里面,直接使用接口。针对iOS来说就是尽量的将对象的属性封装成接口之后,对外暴露接口,而不是对外暴露属性。既然是面向接口编程,那么最彻底的就是使用@protocol了,因为@protocol就是将接口抽象出来。这里主要参考了这篇文章。