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


当前回答

简单但经常被遗忘。根据规格:

一般来说,方法各不相同 具有相同选择器的类 (相同的名字)也必须共享 相同的返回值和参数类型。这 约束是由编译器施加的 允许动态绑定。

在这种情况下,所有相同的命名选择器,即使在不同的类中,也会被认为具有相同的返回/参数类型。这里有一个简单的例子。

@interface FooInt:NSObject{}
-(int) print;
@end

@implementation FooInt
-(int) print{
    return 5;
}
@end

@interface FooFloat:NSObject{}
-(float) print;
@end

@implementation FooFloat
-(float) print{
    return 3.3;
}
@end

int main (int argc, const char * argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];    
    id f1=[[FooFloat alloc]init];
    //prints 0, runtime considers [f1 print] to return int, as f1's type is "id" and FooInt precedes FooBar
    NSLog(@"%f",[f1 print]);

    FooFloat* f2=[[FooFloat alloc]init];
    //prints 3.3 expectedly as the static type is FooFloat
    NSLog(@"%f",[f2 print]);

    [f1 release];
    [f2 release]
    [pool drain];

    return 0;
}   

其他回答

黄金法则:如果你分配了,那么你就释放了!

更新:除非你正在使用ARC

在dealloc中清理。

这是最容易忘记的事情之一——尤其是在以150英里/小时的速度编码时。总是,总是,总是清理dealloc中的属性/成员变量。

我喜欢使用Objc 2属性-新的点表示法-所以这使得清理变得无痛。通常很简单:

- (void)dealloc
{
    self.someAttribute = NULL;
    [super dealloc];
}

这将为您处理发布,并将属性设置为NULL(我认为这是防御性编程——以防dealloc中的另一个方法再次访问成员变量——很少,但也可能发生)。

在10.5中打开GC后,就不再需要这么多了——但是你可能仍然需要清理你创建的其他资源,你可以在finalize方法中做这件事。

我知道我在第一次接触Cocoa编程时忽略了这一点。

确保您了解有关NIB文件的内存管理职责。您负责释放所加载的任何NIB文件中的顶级对象。阅读苹果关于这个主题的文档。

如果您使用的是Leopard (Mac OS X 10.5)或更高版本,则可以使用Instruments应用程序来查找和跟踪内存泄漏。在Xcode中构建程序后,选择使用性能工具> Leaks运行>。

即使你的应用程序没有显示任何泄漏,你可能把对象保存得太久了。在Instruments中,您可以为此使用ObjectAlloc工具。在Instruments文档中选择ObjectAlloc乐器,并通过选择View > detail(它旁边应该有一个复选标记)来显示乐器的详细信息(如果还没有显示的话)。在ObjectAlloc详细信息中的“分配生命周期”下,确保选择“已创建和仍然存在”旁边的单选按钮。

现在,每当您停止记录应用程序时,选择ObjectAlloc工具将在“# Net”列中显示对应用程序中每个仍然活动的对象的引用数。确保不仅要查看自己的类,还要查看NIB文件的顶级对象的类。例如,如果你在屏幕上没有窗口,而你看到一个仍然存在的NSWindow的引用,你可能没有在你的代码中释放它。

使用NSAssert和朋友。 我一直使用nil作为有效对象…特别是发送消息给nil在Obj-C中是完全有效的。 然而,如果我真的想确定一个变量的状态,我使用NSAssert和NSParameterAssert,这有助于轻松跟踪问题。