我知道HIG(这非常方便!),但是在编写Objective-C时,更具体地说,在使用Cocoa(或CocoaTouch)时,您使用了什么编程实践?


当前回答

声明属性

对于所有属性,您通常应该使用Objective-C 2.0声明属性特性。如果它们不是公共的,将它们添加到类扩展中。使用声明的属性使内存管理语义立即清晰,并使您更容易检查dealloc方法——如果您将属性声明分组在一起,您可以快速扫描它们并与dealloc方法的实现进行比较。

在不将属性标记为“nonatomic”之前,您应该仔细考虑一下。正如《Objective C编程语言指南》所指出的,属性在默认情况下是原子的,并且会产生相当大的开销。此外,简单地将所有属性都设置为原子化并不能使应用程序具有线程安全性。当然,还要注意,如果你没有指定“nonatomic”,并且实现你自己的访问方法(而不是合成它们),你必须以原子的方式实现它们。

其他回答

确保您收藏了调试魔术页面。这应该是你在寻找Cocoa bug的源头时碰壁的第一站。

例如,它会告诉你如何找到你第一次分配内存的方法,后来导致崩溃(比如在应用程序终止期间)。

编写单元测试。您可以在Cocoa中测试许多在其他框架中可能比较困难的事情。例如,对于UI代码,您通常可以验证事物是否按照应有的方式连接,并相信它们在使用时能够正常工作。你可以很容易地设置状态和调用委托方法来测试它们。

在编写内部测试时,也不会有公共、受保护和私有方法可见性。

声明属性

对于所有属性,您通常应该使用Objective-C 2.0声明属性特性。如果它们不是公共的,将它们添加到类扩展中。使用声明的属性使内存管理语义立即清晰,并使您更容易检查dealloc方法——如果您将属性声明分组在一起,您可以快速扫描它们并与dealloc方法的实现进行比较。

在不将属性标记为“nonatomic”之前,您应该仔细考虑一下。正如《Objective C编程语言指南》所指出的,属性在默认情况下是原子的,并且会产生相当大的开销。此外,简单地将所有属性都设置为原子化并不能使应用程序具有线程安全性。当然,还要注意,如果你没有指定“nonatomic”,并且实现你自己的访问方法(而不是合成它们),你必须以原子的方式实现它们。

#import "MyClass.h"

@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end

@implementation MyClass

这是一个微妙但很方便的方法。如果你将自己作为委托传递给另一个对象,在dealloc之前重置该对象的委托。

- (void)dealloc
{
self.someObject.delegate = NULL;
self.someObject = NULL;
//
[super dealloc];
}

这样做可以确保不再发送更多的委托方法。当您即将dealloc并消失在以太中时,您希望确保没有任何东西可以意外地向您发送更多消息。还记得自己。someObject可以被另一个对象保留(它可以是一个单例对象或在自动释放池中或其他任何对象),直到您告诉它“停止向我发送消息!”,它才会认为您即将被释放的对象是公平的游戏。

养成这种习惯将使您避免大量令人痛苦的调试的奇怪崩溃。

同样的原理也适用于键值观察和NSNotifications。

编辑:

更有防御性的改变:

self.someObject.delegate = NULL;

成:

if (self.someObject.delegate == self)
    self.someObject.delegate = NULL;