SoFunction
Updated on 2025-04-03

Detailed explanation of the timing of controlling NSLog output in iOS

-(void)saveDEBUGlog{
  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  NSString *documentDirectory = [paths objectAtIndex:0];
  
  NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  [dateFormatter setDateFormat:@"yyyy_MM_dd_HH_mm_ss"];
  NSString *currentDateStr = [dateFormatter stringFromDate:[NSDate date]];
  NSString *fileName = [NSString stringWithFormat:@"testLog_%@.log",currentDateStr];
  
  NSString *logFilePath = [documentDirectory stringByAppendingPathComponent:fileName];
  // Delete the existing files first  NSFileManager *defaultManager = [NSFileManager defaultManager];
  [defaultManager removeItemAtPath:logFilePath error:nil];
  
  // Enter log to file  freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stdout);
  freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);
}

This method mainly calls the freopen method to write, where stdout and stderr include most of the exception outputs in iOS.

2. Control log output according to Bool value

When users encounter various problems when using the app, when they and the testing team are not able to locate the reasons, it is the best way to analyze them to send the user the log of the key points. But how to intercept a part of the log during the app running process and save it? Can you control the reading and writing of logs like a switch? Discover the inspiration obtained by reading the MQTTLog source code.

First, replace the NSLog with the following macro, and use SLOG in the project to output

#define SLOG(fmt, ...) if (reportLoggerIsOpen) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
From the macro definition, we can see that reportLoggerIsOpen is a switch that controls the output of Log. For the definition of reportLoggerIsOpen, extern is first declared in the h file, and then implemented in the m file.

.h file

#import <Foundation/>

extern BOOL reportLoggerIsOpen;
.m document
BOOL reportLoggerIsOpen = NO;

+ (void)setLogOpen:(BOOL)open {
  reportLoggerIsOpen = open;
}

Through the setLogOpen method, you can freely control log writing. For example, if you need to crawl the log of the login module, then pass in true before login. After login, pass in false to keep only the login module login module.