3

我现在正在编写 ios 应用程序一段时间。但是我的应用程序仍然经常崩溃,并且需要时间才能使它们非常稳定。我觉得这很烦人。

那么,是否有任何关于防崩溃编程 iOS 应用程序的编程模式?

4

3 回答 3

4
  • 打开编译器警告。删除所有警告。
  • 运行静态分析器。删除所有警告。
  • 使用 GuardMalloc 和/或 Scribbling 运行。
  • 删除所有泄漏
  • 移除所有僵尸
  • 编写单元测试
  • 编写高级实时错误检测(例如断言)
  • 在添加功能之前修复错误。
  • 使用源代码控制和持续集成。
  • 读。提升。
于 2012-08-13T23:31:38.357 回答
1

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

阻止一些执行更复杂检查的代码 - 它仅对您的开发版本有效,而不是用于发布/分发。

于 2012-08-14T00:41:43.757 回答
0

您可能已经这样做了,但这是我所做的:

  1. 使用调试器/模拟器转到应用程序中的每个屏幕,然后选择“模拟内存警告”。返回上一个屏幕。这会导致 viewDidLoad 中现有的 UIView 对象和变量分配被重新分配(这可能导致错误的指针引用)。

  2. 确保在 dealloc 中使任何正在运行的计时器无效。

  3. 如果对象 A 已将自己设为对象 B 的委托,请确保在对象 A 的 dealloc 中清除它。

  4. 确保清除 dealloc 中的所有通知观察者。

于 2012-08-14T00:03:49.473 回答