最基本的调试是NSLog及DEBUG预处理器宏

最基本的调试是NSLog及DEBUG预处理器宏

在系统控制台显示日志信息运行应用程序时是最早调试机制之一,利用log你可以查看应用程序的运行记录,当程序运行完毕,你可以长时间查看。此外,您的应用程序运行期间,可以观察所产生并写入到控制台,在您的应用程序它们所描述正在发生的事件的日志消息。作为一个开发者你是用NSLog的在console中显示的文本和信息的完全控制权,log可以发现即使是最难查找一个应用程序的问题.

此文档关于有关NSLog的功能及DEBUG预处理程序宏实际考虑为调试有用的对话

下面是NSLog调用的一个例子。

NSString *message = @"test message";
NSLog( @"Here is a test message: '%@'", message );

并且,对于上述说法,控制台输出将显示如下:

Here is a test message: 'test message'

这真的就是这么简单!而且,在这个文件中的这个时刻,你现在有足够的信息来开始使用NSLog的调试您的应用程序.但是,你应该继续往下看:在本文档的剩余部分补充说,你可以使用授权您可以在您的项目更有效地使用记录更多详细信息。

此文档适用于所有iOS和OS X开发,本示例假定正在使用Xcode的读者,是熟悉的Objective-C语言,并了解使用C语言预处理程序的基础知识。

[TOC]

在哪里可以找到NSLog的输出

有史以来Founction框架的NSLog功能一直适用于iOSOSX的个个版本。因此,您可以依赖它是可用于在任何苹果的平台,让您的应用程序将运行调试用的。NSLog的输出消息记录到苹果系统日志工具或控制台应用程序(通常以时间及进程ID作为前缀)。许多系统框架中使用NSLog的用于记录异常和错误,但不要求来限制及其使用于上述目的这也是完全可以接受的使用NSLog的输出变量值,参数,函数结果,堆栈跟踪等信息,所以你可以看到什么是在你的代码在运行时发生。

控制台输出可以出现在许多地方,包括(但不限于)Xcode和控制台应用程序,参考有关从您的应用程序的调用NSLog的找到控制台输出的更多信息,请参见技术Q&A QA1747:调试部署iOS应用

如何调用NSLog的

Founction框架NSLog功能的工作就像标准C库printf函数,最大的区别在于格式字符串被指定为“* NSString的”类型的值,而不是C风格的字符串

简单的例子

这里是展示如何调用NSLog的一个例子:

NSString *outputData = @"A quick brown fox jumps over a lazy dog!";
 
NSLog( @"text: %@", outputData );
 
/* Comment:
 
    @"text: %@" - is the printf style formatting template for output (an NSString *)
 
    outputData - refers to to the text we wish to display (also an NSString *)
 
*/

而且,这里是输出的显示方式:

text: A quick brown fox jumps over a lazy dog!

高级详细信息

出现用于NSLog的函数定义如下:

void NSLog(NSString *format, ...);

注意第一个参数是一个格式化字符串,它可以含有意味着额外的参数之后期望特殊的替换标记.如果关心和关注不能采取措施,确保格式字符串的内容匹配起来,其余的参数,您的应用程序可能会崩溃(或者,至少是,它将输出不可用的数据到控制台)

像printf函数,使用NSLog的标记替换:

然而,出现在Objective-C%@,用于指示及其对应的参数应该是一个Objective-C的对象一个额外取代标记提供。

除了%@替换标识所有常规的printf风格替换标记是供您使用

关于有关NSLog的使用的替换标记的详细信息,请参见“字符串编程指南”的“字符串格式说明”部分。

好东西要在日志文件包括

日志记录允许您创建描述您的应用程序,你可以在你的闲暇之后分析操作的抄本。因此,你想在你的日志尽可能多的有用信息,这样更容易在你的应用程序运行期间让你真正看到正在发生的事情。

下面是一些通常包含在一些解释日志的一些项目:

逻辑和分支

新增您代码的逻辑内部的日志语句将帮助您了解正在被执行的部分,并正在使用你的逻辑,分支机构

日志对于十分复杂的程序落实十分有用的,你可以看到运行期间的程序逻辑。

独特且易于查找文本模式

在每个日志声明,它是有用的,包括一些独特的并且容易找到的文本模式,所以如果你确定该日志语句有问题,可以很容易地通过你的源文件搜索和找到它的位置

变量和属性值

你在你的应用程序关键地方打印变量和属性可以验证这些值是否是允许的范围之内。在日志打印错误信息,可以帮助你识别超出值范围的这一种情况。

除了用%@标记,任何在Printf使用的标记都可以在格式化字符串中使用。这将允许您显示许多不同类型的值,更多关于格式化信息你可以参考“字符串编程指南”的“字符串格式说明”部分

printf函数提供了大量用于打印数字替换标记(例如%d,%ld,%f)为方便起见,你可以使用Objective-C的Box能力,以节省时间,避免编译器警告。例如,以下内容:

double myNumber = 7.7;
NSLog(@"number: %@", @(myNumber));

打印如下

number: 7.7

这种技术适用于所有数字类型,编译器意识到(或签定任何大小的无符号整数或浮点数 - 8,16,32或64位),并且将任何必要的强制类型转换为你而不会产生的任何编译器警告

谁正在被调用

分析应用程序的操作是至关重要的,你可以知道那些程序那些功能被顺序调用。在这种情况下,它是添加接近的方法和函数定义之初即只需打印出函数名称的声明NSLog的一个很好的主意。

- (void)pressButton:(id)sender
{
    NSLog( @"calling: %s", __PRETTY_FUNCTION__ );
    ....

这里,预定义的编译时间变量PRETTY_FUNCTION(一个C风格字符串)被用于打印函数的名称调用.当你分析大量的功能代码,你想知道正在调用你代理方法的层次是非常有用的。

以上将打印在console以下内容:

calling: -[MyObjectClassName pressButton:]

PRETTY_FUNCTION编译time变量和其他类似在技术Q&A QA1669讨论:改进了日志记录在Objective-C

记录你的堆栈信息

当检查崩溃日志,在堆栈中是非常宝贵找出导致的任何特定情况下的连锁事件。当使用NSLog进行调试,您可以通过调用NSThread-callStackSymbols类方法随时检索当前堆栈跟踪的副本。你可以在堆栈中使用%@打印NSArray的堆栈的信息。

NSLog(@"%@", [NSThread callStackSymbols]);

上面的语句输出是下面的样子。

2014-04-30 18:44:30.075 AVCustomEdit[52779:60b] (
 0  AVCustomEdit      0x0000efa6 -[APLSimpleEditor buildCompositionObjectsForPlayback:] + 278
 1  AVCustomEdit      0x0000686e -[APLViewController viewDidAppear:] + 590
 2  UIKit             0x007a4099 -[UIViewController _setViewAppearState:isAnimating:] + 526
 3  UIKit             0x007a4617 -[UIViewController __viewDidAppear:] + 146
 4  UIKit             0x007a49aa -[UIViewController _executeAfterAppearanceBlock] + 63
 5  UIKit             0x0069f0d0 ___afterCACommitHandler_block_invoke_2 + 33
 6  UIKit             0x0069f055 _applyBlockToCFArrayCopiedToStack + 403
 7  UIKit             0x0069ee9a _afterCACommitHandler + 568
 8  CoreFoundation    0x029db2bf __CFRunLoopDoObservers + 399
 9  CoreFoundation    0x029b9254 __CFRunLoopRun + 1076
 10 CoreFoundation    0x029b89d3 CFRunLoopRunSpecific + 467
 11 CoreFoundation    0x029b87eb CFRunLoopRunInMode + 123
 12 GraphicsServices  0x0318b5ee GSEventRunModal + 192
 13 GraphicsServices  0x0318b42b GSEventRun + 104
 14 UIKit             0x00681f9b UIApplicationMain + 1225
 15 AVCustomEdit      0x000026bd main + 141
 16 libdyld.dylib     0x0269e701 start + 1
)

该DEBUG预处理程序宏

简而言之,该DEBUG处理器宏作用一样,你可以打开和关闭一部分的调试代码。具体地,Debug宏旨在被用于打开和关闭相关的调试中不同部分源代码.在Xcode的默认配置中,调试默认为1,发布为0.而且,你可以利用它来自动地包含额外的调试和记录代码的调试版本。

下面是Debug使用的一个例子。

- (void)pressButton:(id)sender
{
#if DEBUG
    NSLog(@"preparing to press button!");
#endif
    [self prepareForButtonPress];
 
#if DEBUG
    NSLog(@"pressing button!");
#endif
 
    [self activatePressButtonSequence:self withCompletion:^{
#if DEBUG
        NSLog(@"button sequence complete.");
#endif
            [self buttonPowerDown];
        }];
    NSLog(@"This line has no DEBUG macro, so it gets printed in both debug and release builds!");
}

调试版本(DEBUG == 1)将输出下面的信息

preparing to press button!
pressing button!
button sequence complete.
This line has no DEBUG macro, so it gets printed in both debug and release builds!

发布版本(DEBUG == 0)将输出下面的信息

This line has no DEBUG macro, so it gets printed in both debug and release builds!

NSLog需要时间去执行,如果你在你的应用程序里面加了很多这样的代码,将加大你程序的运行时间。在测试过程中,这通常不是问题。但是在发布的时候最好删除所有的打印,让用户体验最好的性能,不是打印一大堆看不懂的信息。正因为如此,开发者可以使用Debug宏可以让NSLog只有在调试的时候出现。

在Xcode里面的DEBUG

在Xcode中DEBUG定义调试模式,预编译宏可以编译DEBUG可以让你DEBUG模式运行程序。如果你不确定你是否定义了,可以通过打开你工程Build Setting搜索预处理,确保在Debug模式DEBUG ==1。如果还没有定义,你可以手动的添加,预编译宏是区分大小写的。

​ 图一在Xcode设置DEBUG预编译宏

Paste_Image.png

添加更多的LOG

如果你已经添加了log你还是找不到问题的所在,你可以添加很多的Log去查找。继续添加记录到您的应用程序,直到你能够获取足够的信息,以便您能够明白发生了什么。

NSLog是调试的朋友

每一个iOS或者OSX的开发人员无时无刻的使用NSLog调试你的程序,而且,你知道开发者可能对如何使用它的一些有趣的想法可能对你有帮助。如果您对NSLog的任何其他问题或需要帮助调试,请询问您的问题在适当的Mac或iOS开发者论坛调试的部分。

如果您对本文有任何意见,请通过反馈标签提交的文档的底部

更多的资源

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏walterlv - 吕毅的博客

WPF 跨应用程序域的 UI(Cross AppDomain UI)

发布于 2017-11-12 16:36 更新于 2017-11...

1792
来自专栏Golang语言社区

Golang事务模型

序言 笔者在《软件设计的演变过程》一文中,将通信系统软件的DDD分层模型最终演进为五层模型,即调度层(Schedule)、事务层(Transaction DSL...

3506
来自专栏牛客网

美团Android三面面试经历

之前在阿里实习,回来后只参加了美团的面试。最后有幸拿到了阿里的转正offer和点评平台的offer。这里简单地把我在美团面试过程中记录的一些问题分享一下,总体来...

4916
来自专栏進无尽的文章

编码篇-使用GDataXMLNode解析XML数据

在实际的开发中数据解析是很普遍的事,一般网络请求返回的数据有两种格式:XML和JSON。关于JSON的解析已是主流,满大街的解析方式。而XML的数据格式确实是很...

1311
来自专栏张善友的专栏

用.NET Framework 2.0创建 Form设计器[翻译]

    这两天赶鸭子上驾,学习Form设计器,下面这篇在Msdn Magazine的文章可谓是经典,这两天学习了感觉还是做个翻译出来,更能够加强理解。对各位同...

2136
来自专栏互联网杂技

内存卡存储原理,你知道吗?

1、 简介: SD卡(Secure Digital Memory Card)是一种为满足安全性、容量、性能和使用环境等各方面的需求而设计的一种新型存储器...

4406
来自专栏比原链

剥开比原看代码17:比原是如何显示交易的详细信息的?

Gitee地址:https://gitee.com/BytomBlockchain/bytom

821
来自专栏腾讯移动品质中心TMQ的专栏

管中窥豹:结合NewApi实践来了解Lint代码扫描

导读 lint是著名的C/C++语言静态代码分析工具之一,Android Lint顾名思义,针对Android的静态代码分析工具,能够对Android项目中潜在...

21110
来自专栏程序员的SOD蜜

单数据库,多数据库,单实例,多实例不同情况下的数据访问效率测试

最近公司的项目准备优化一下系统的性能,希望在数据库方面看有没有提升的空间,目前压力测试发现数据库服务器压力还不够大,Web服务器压力也不是很大的情况下,前台页面...

24610
来自专栏WindCoder

iOS集中和解耦网络:具有单例类的AFNetworking教程

当涉及iOS架构模式时,模型 - 视图 - 控制器(MVC)设计模式对于应用程序的代码库的长寿和可维护性是非常有用的。通过将它们解耦从而使类可以很容易地被重用或...

2481

扫码关注云+社区

领取腾讯云代金券