你是否清除了你的观察者?
一个简单的错误是添加观察者对象,但不清除它们。 在这种情况下,KVO 将持续的发送消息,但接收者可能已经被释放了,于是引发了崩溃。绕开它的一种方法是使用成熟的框架如 ReactiveCocoa,还有一些轻量级的库用起来也不错。
还有一种方法是,无论你何时创建了一个新观察者,立刻在 dealloc 里写一个移除。然而,这个过程可以自动执行:比直接添加观察者更好的办法是,你可以创建一个自定义对象来让它帮你进行添加。这个对象负责添加观察者并在它自己的 dealloc 里移除它。这样做的优势是你的观察者的生命周期会和这个对象的生命周期一样。这意味着创建这个对象等价于添加了一个观察者。然后你可以将它存为一个属性,当容器对象被析构,属性会自动被设置为 nil,然后移除观察者。
有一点相对详细的关于这种技术的解释,包括一段简单的代码,可以在这里被找到。一个小巧的库可以实现这个功能,那就是 THObserversAndBinders,或者你可以看看 Facebook 的 KVOController。
另一个关于 KVO 的问题是回调可能会从你预料之外的线程上返回 (就像我们在开头线程部分描述的那样)。同样的方案,使用一个对象来解决这个问题 (如以上所说),你可以确保所有的回调会在一个确定的线程上返回。
视图的生命周期
当处理视图的时候,有很多可能的 bug 会出现。一个常见的错误是在视图还没有初始化的时候就使用它们。或者,你可能在一个视图只是初始化,却还没有设置尺寸时使用就使用它们。这里的关键是在视图生命周期中,找到合适的节点去安排代码。花时间去深入理解它们是如何工作,相对于以后调试的时间来说,绝对是稳赚不赔的。
当你往 iPad 上 移植一个已有的 app 时,这有时也是一个常见的 bug 原因。与此前不曾遇到的情况不同,你现在可能需要担心一个视图控制器是否是一个子视图控制器,它们如何响应旋转事件,还有一些细微区别。针对这种情况,自动布局可能会有一些帮助,它可以自动响应很多类似的变化。
一个常见的错误是我们总是创建一个视图,添加一些约束,然后将它添加进父视图里。不过,为了让大部分约束能够工作,这个视图是需要添加在父视图的视图层级中的。勉强算作好消息的是,大部分情况下这会直接让你的代码崩溃,然后你可以很快的找到 bug。
摘抄于:调试核对清单 0.0