NSLog里面干了啥?(摘自GNUStep)

NSLog的实现

void NSLog(NSString* format, ...)
{
  va_list ap;

  va_start(ap, format);
  NSLogv(format, ap);
  va_end(ap);
}

NSLogv()函数主要拼接了系统打印时间、线程信息以及要打印函数传入的参数(真正要打印的东西)

void NSLogv(NSString* format, va_list args)
{
  NSMutableString    *prefix;
  NSString              *message;
  NSString              *threadName = nil;
  NSThread              *t = nil;
  
  ger            tid = GSPrivateThreadID();
  static int        pid = 0;

  if (_NSLog_printf_handler == NULL)
    {
      _NSLog_printf_handler = *_NSLog_standard_printf_handler;
    }

  if (pid == 0)
    {
      pid = (int)getpid();
    }

  if (GSPrivateDefaultsFlag(GSLogThread) == YES)
    {
      t = GSCurrentThread();
      threadName = [t name];
    }
  prefix = [[NSMutableString alloc] initWithCapacity: 1000];

  NSString  *fmt;
  NSString  *cal;

  if (GSPrivateDefaultsFlag(GSLogOffset) == YES)
    {
      fmt = @"%Y-%m-%d %H:%M:%S.%F %z";
    }
  else
    {
      fmt = @"%Y-%m-%d %H:%M:%S.%F";
    }

  cal = [[NSCalendarDate calendarDate] descriptionWithCalendarFormat: fmt];
// 拼接系统日期
  [prefix appendString: cal];
  [prefix appendString: @" "];
  [prefix appendString: [[NSProcessInfo processInfo] processName]];
  if (nil == t || ((NSThread*)tid == t && nil == threadName))
    {
      [prefix appendFormat: @"[%d:%"PRIuPTR"] ",
        pid, tid];
    }
  else if (nil == threadName)
    {
      [prefix appendFormat: @"[%d:%"PRIuPTR",%p] ",
        pid, tid, t];
    }
  else
    {
      [prefix appendFormat: @"[%d:%"PRIuPTR",%@] ",
        pid, tid, threadName];
    }
    
  message = [[NSString alloc] initWithFormat: format arguments: args];
  [prefix appendString: message];
  [message release];
  if ([prefix hasSuffix: @"\n"] ==  NO)
    {
      [prefix appendString: @"\n"];
    }

  if (nil == myLock)
    {
      GSLogLock();
    }

    // 直接用函数指针调用函数,采用递归锁保证线程同步安全
  (*lockImp)(myLock, @selector(lock));

  _NSLog_printf_handler(prefix);

  (*unlockImp)(myLock, @selector(unlock));

  [prefix release];
}

// 将打印的字符串采用UTF-8编码写入NSData流,并通过write函数写入handle所指的文档

static void _NSLog_standard_printf_handler(NSString* message)
{
  NSData    *d;
  const char    *buf;
  unsigned    len;


  static NSStringEncoding enc = 0;


  if (enc == 0)
    {
      enc = [NSString defaultCStringEncoding];
    }
    // 将字符串采用UTF-8编码写入NSData流
  d = [message dataUsingEncoding: enc allowLossyConversion: NO];
  if (d == nil)
    {
      d = [message dataUsingEncoding: NSUTF8StringEncoding
         allowLossyConversion: NO];
    }


  if (d == nil)        // Should never happen.
    {
      buf = [message lossyCString];
      len = strlen(buf);
    }
  else
    {
      buf = (const char*)[d bytes];
      len = [d length];
    }
    // 将要输出的信息写入文件
    write(_NSLogDescriptor, buf, len);
}

总结:NSLog函数本质上就将输入的参数拼接成字符串转成NSData流后调用wirte函数写入handle所指的文档

posted @ 2021-01-13 21:03  ITRyan  阅读(129)  评论(0)    收藏  举报