菜鸟教程小白 发表于 2022-12-13 02:11:02

ios - 在保持向后兼容性的同时采用 os_log API


                                            <p><p>我正在尝试向库中添加对新日志记录和事件跟踪 API 的支持,以便为尚未采用最新版本操作系统(iOS 或 macOS)的库用户保持向后兼容性.我正在为每个级别的日志记录定义自定义日志记录宏,然后为旧操作系统定义回退到 <code>NSLog</code>。我已经完成了这项工作,但有一个问题。</p>

<p>如果您希望它们显示在日志输出中,新 API 要求您将任何非常量、非标量值显式标记为 <code>public</code>。这就是我的宏调用的样子:</p>

<pre><code>UZKLogInfo(&#34;Reading file %{public}@ from archive&#34;, fileName);
</code></pre>

<p>使用包含 <code>os_log</code> 的 SDK(例如 iOS 10.0 或更高版本)可以正常编译,但是当我使用早期版本编译时,我的宏会退回到 <code>NSLog</code>,我收到编译器警告:</p>

<blockquote>
<p>Using &#39;public&#39; format specifier annotation outside of os_log()/os_trace()</p>
</blockquote>

<p>打印出来的日志是这样的:</p>

<pre><code>Reading file &lt;decode: missing data&gt; from archive
</code></pre>

<p>这是我的宏定义的简化版(只包括<code>info</code>定义和简化条件:</p>

<pre><code>#if UNIFIED_LOGGING_SUPPORTED
    @import os.log;

    #define UZKLogInfo(format, ...) os_log_info(OS_LOG_DEFAULT, format, ##__VA_ARGS__);
#else // Fall back to regular NSLog
    #define UZKLogInfo(format, ...) NSLog(@format, ##__VA_ARGS__);
#endif
</code></pre>

<p>有没有办法在后备情况下从 <code>format</code> 中去除“{public}”文本(某种字符串替换?)?或者是否有另一种方法来支持新旧 API 而不会放弃我一直在日志中显示的信息级别?我需要使用宏(根据 <a href="https://developer.apple.com/videos/play/wwdc2016/721/" rel="noreferrer noopener nofollow">last year&#39;s WWDC session on the topic</a> ,否则我会丢失调用站点元数据。</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>我选择在宏中进行 <code>NSString</code> 替换,并将编译器警告作为其中的一部分进行替换,因此可以针对每一行执行此操作,而不是针对整个文件或项目全局执行此操作.它看起来像这样:</p>

<pre><code>#if UNIFIED_LOGGING_SUPPORTED
    @import os.log;

    #define UZKLogInfo(format, ...) os_log_info(OS_LOG_DEFAULT, format, ##__VA_ARGS__);

#else // Fall back to regular NSLog

    #define _removeLogFormatTokens(format) [@format stringByReplacingOccurrencesOfString:@&#34;{public}&#34; withString:@&#34;&#34;]
    #define _stringify(a) #a
    #define _nsLogWithoutWarnings(format, ...) \
      _Pragma( _stringify( clang diagnostic push ) ) \
      _Pragma( _stringify( clang diagnostic ignored &#34;-Wformat-nonliteral&#34; ) ) \
      _Pragma( _stringify( clang diagnostic ignored &#34;-Wformat-security&#34; ) ) \
      NSLog(_removeLogFormatTokens(format), ##__VA_ARGS__); \
      _Pragma( _stringify( clang diagnostic pop ) )

    #define UZKLogInfo(format, ...) _nsLogWithoutWarnings(format, ##__VA_ARGS__);
#endif
</code></pre>

<p>它是这样称呼的:</p>

<pre><code>UZKLogInfo(&#34;Message: %@&#34;, anObjectToLog);
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 在保持向后兼容性的同时采用 os_log API,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/45022233/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/45022233/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 在保持向后兼容性的同时采用 os_log API