我现在正在编写 ios 应用程序一段时间。但是我的应用程序仍然经常崩溃,并且需要时间才能使它们非常稳定。我觉得这很烦人。
那么,是否有任何关于防崩溃编程 iOS 应用程序的编程模式?
我现在正在编写 ios 应用程序一段时间。但是我的应用程序仍然经常崩溃,并且需要时间才能使它们非常稳定。我觉得这很烦人。
那么,是否有任何关于防崩溃编程 iOS 应用程序的编程模式?
1)使用弧。
ARC 的学习曲线很小,我在 SO 上读到的最大问题是人们实例化对象但忘记将对象分配给强 ivar(或属性),因此对象神秘地消失了。无论如何,好处是如此引人注目,您应该掌握这一点。当您这样做时,您现在必须保留的大部分内存管理内容都会消失。
2)构建干净
构建时永远不应该有警告。如果你有一堆,当一个真正的问题出现时,它就会被你习惯于忽略的垃圾线埋没。专业的程序员构建干净。
3) 使用分析
Xcode/llvm 有一个惊人的分析器 - 使用它 - 它位于 Product 菜单项下。然后清理它给你的每一个警告。
4)使用正确的配置
我总是有一个发布(或分发)配置、一个 ReleaseWithAsserts 和调试。我只在使用 lldb 时使用 Debug,因为代码要大得多,并且它的执行方式与优化的编译方式不同。ReleaseWithAsserts 与 Debug 类似,但去掉了 Debug=1 预处理器标志,并将优化器设置为 -Os(Release 的默认值)。
最后,Release/Distribution 配置在预处理宏中有以下内容:
NS_BLOCK_ASSERTIONS=1 NDEBUG
第一个关闭所有“NSAssert()”行,第二个关闭所有“assert()”语句。这样,您的交付代码中就没有断言处于活动状态
5) 使用大量的断言。
Asserts 是程序员可以拥有的最好的朋友之一。我在这里看到了很多问题,如果程序员只使用它们就永远不会写出来。开销在于键入它们,因为(在我的使用中)它们在 Release 配置中被编译掉。
每当你从另一个来源获得一个对象时,断言它的存在(即:
MyObject *foo = [self someMethod];
assert(foo);
这很容易输入,但是当一个 nil 对象在数千条指令之后导致问题时,可以节省您数小时的调试时间。您也可以在课堂上断言:
MyObject *foo = [self someMethod];
assert([foo isMemberOfClass:[MyObject class]]);
当您从字典中提取对象时,这特别有用。
您可以将断言放在方法的开头,以验证您收到的对象也不是 nil。
您可以断言某个变量具有值:
assert(i>1 && i<5);
同样,在除发布/分发配置之外的所有配置中,断言都是“活动的”,但在该配置中它们被编译出来。
NSAssert 类似——但您必须根据参数的数量使用不同的宏。
NSAssert(foo, @"Foo was nil");
NSAssert1(foo, @"Foo was nil, and i=%d", i);
...
6)使用选择性日志来确保应该发生的事情是
您可以定义自己的 Log 宏,该宏会为 Release/Distribution 编译出来。将此添加到您的 pch 文件中:
#ifndef NDEBUG
#define MYLog NSLog
#else
#define MYLog(format, ...)
#endif
这指出了另一点 - 您可以使用:
#ifndef NDEBUG
...
#endif
阻止一些执行更复杂检查的代码 - 它仅对您的开发版本有效,而不是用于发布/分发。
您可能已经这样做了,但这是我所做的:
使用调试器/模拟器转到应用程序中的每个屏幕,然后选择“模拟内存警告”。返回上一个屏幕。这会导致 viewDidLoad 中现有的 UIView 对象和变量分配被重新分配(这可能导致错误的指针引用)。
确保在 dealloc 中使任何正在运行的计时器无效。
如果对象 A 已将自己设为对象 B 的委托,请确保在对象 A 的 dealloc 中清除它。
确保清除 dealloc 中的所有通知观察者。