【问题标题】:Dynamically turning on NSLogs动态开启 NSLogs
【发布时间】:2023-03-17 06:52:01
【问题描述】:

我目前正在使用以下 DebugLog 宏

#if defined(DEBUG) && defined(useDebugLogs)
#define DebugLog( s, ... ) NSLog( @"<%s:(%d)> %@", __PRETTY_FUNCTION__, __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DebugLog( s, ... ) 
#endif

但是,现在通过允许远程记录的试飞,这有点过时了。

基本上我想做的是在我的 settings.plist 中添加一个开关,以允许用户打开远程日志记录。

我看过这个教程 http://jomnius.blogspot.com/2011/09/how-to-do-dynamic-debug-logging-in.html

但是,这是一个非常糟糕的解释,实际上似乎不起作用。

【问题讨论】:

  • 你试过NSLogger吗?
  • DEBUG 仅在...(惊喜)调试期间定义。在发布代码中,这是行不通的。
  • @AndyFriese 不过我没用过,我在该教程的 cmets 中看到过,但似乎太多了。我只想要一个简单的开关
  • 为什么不通过改进实施、发布更新、改进实施、发布更新、改进实施、发布更新、改进实施、发布更新、改进您的实施来启用它们并控制您收到的消息实施、发布更新……

标签: ios objective-c macros c-preprocessor nslog


【解决方案1】:

好吧,IMO 最好的方法是始终发送日志并调整您的实施,以便您准确地看到您想要的。您要么需要分析,要么不会使用它们。有错误,或者没有。通过它们工作并提高您的信噪比。反正……

您可以为此目的创建一个专用函数。它可以根据您的实现中的某些变量有条件地记录或不记录。请注意,您可以通过调用NSLogv 而不是NSLog 来转发您的va_list,或者您可以使用-[NSString initWithFormat:arguments:] 将消息+参数转发到其他地方:

MONDebugLog.h

extern void MONDebugLog(NSString * format, ... ) NS_FORMAT_FUNCTION(1,2);

MONDebugLog.m

void MONDebugLog(NSString * format, ... ) {

    enum {
        MONLog_Undefined,
        MONLog_Enable,
        MONLog_Disable
    };

    static int DoLog = MONLog_Undefined;
    if (MONLog_Undefined == DoLog) {
        DoLog = ...load from plist or defaults and set to Log_Enable or Log_Disable...;
    }

    if (MONLog_Disable == DoLog) {
        return;
    }
    va_list arguments;
    va_start(arguments, format);
    NSString * str = [[NSString alloc] initWithFormat:format arguments:arguments];
    va_end(arguments);
    ...now log or xmit str...
}

【讨论】:

    【解决方案2】:

    如果您只想打开或关闭日志记录,那么有一个简单而强大的解决方案。这个想法是将stderr重定向到/dev/null:

    #include <fcntl.h>
    #include <unistd.h>
    
    void setLoggingEnabled(BOOL enabled)
    {
        static int copyOfStdErr = -1;
        if (enabled) {
            if (copyOfStdErr == -1)
                return;
            dup2(copyOfStdErr, STDERR_FILENO);
            close(copyOfStdErr);
            copyOfStdErr = -1;
        } else {
            if (copyOfStdErr != -1)
                return;
            copyOfStdErr = dup(STDERR_FILENO);
            int fd = open("/dev/null", O_WRONLY);
            dup2(fd, STDERR_FILENO);
            close(fd);
        }
    }
    

    这个解决方案有一些优点:

    • 您不必在代码中使用自己的日志记录机制,它只适用于NSLog
    • 不涉及预处理器魔法。
    • 它也适用于发出输出的第三方库。

    【讨论】:

      【解决方案3】:

      你可以试试这样的:

      #define boolDebug_IsActivated       [[NSUserDefaults standardUserDefaults] boolForKey:@"UseDebug"]
      
      #define DebugLog( s, ... ) \
      if (boolDebug_IsActivated) {\
          NSLog( @"<%s:(%d)> %@", __PRETTY_FUNCTION__, __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] );\
      } \
      else {\
      }
      

      当您想激活/停用时,只需更改NSUserDefaults中的对象值“UseDebug”即可。

      例子:

      [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:NO] forKey:@"UseDebug"];
      DebugLog(@"comment that should not appear");
      [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"UseDebug"];
      DebugLog(@"comment that should appear");
      

      【讨论】:

      • 这似乎是最简单的解决方案。但它会每次都检查 UserDefaults 吗?看起来会很慢。
      猜你喜欢
      • 2013-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-19
      • 1970-01-01
      • 2011-07-29
      • 1970-01-01
      相关资源
      最近更新 更多