适当的Objective-C助手“Wannabe”私人方法?

虽然我讨厌在这个问题上击败一匹马(我已经阅读了关于此的各种文章),但我想在创建我自己的“自己的约定”之前获得更多关于这个问题的意见,以便在编写时使用在Objective-C中。

我想弄清楚的约定最终是如何(使用生产级代码的最佳编码实践)在类中使用私有方法。 来自C#的背景,当我编写类时,通常会有一个代码块在多个公共方法中重复(例如错误检查或WCF服务连接设置)。 我通常会创建一个此代码块,并将其放在一个私有方法中,仅供这些公共方法访问。 这样,如果我需要进行更改,我只需要在一个位置执行此操作,而不是在类中的10个不同位置,但是从不让用户能够调用此私有方法。 例如:

public Class A { public void method1() { doErrorChecking() // Do more stuff } public void method2() { doErrorChecking() // Do more stuff } private doErrorChecking() { //Error Checking Code} } 

我知道没有真正的方法可以在Objective-C中真正使最后一个方法成为私有,但是我真的想确保当我在Objective-C中为iOS开发创建所有未来的类时,我遵循可用的最佳实践未来的代码重构将不再需要(希望如此)。 我注意到人们谈论类别,其他人只是不把方法放在@interface文件中,其他人使用扩展方法。 目前我只是将方法实现放在@implementation文件中,而不是接口文件。 我也让“想要”的私有方法有一个非常独特的名称,因此子类或覆盖方法不是问题。 这是我应该遵循的道路吗? 或者对于这些特殊情况,有更好的方法吗?

是的,想要将您的function提取到另一种方法中是完全合理的。 在我看来,最好的方法是使用类继续 ,您可以将私有方法声明放入。它可以在.m文件中的@implementation块之上,因此它不在公共头中。

 @interface MyClass () - (void)_privateMethod:(id)arg; @end 

类继续和普通类别(例如@interface MyClass (PrivateMethods) )之间的区别在于编译器将要求您在主@implementation块中实现方法,而不是使用单独的@implementation MyClass (PrivateMethods)块。 在实现您所描述的辅助方法时,这可以说是可取的。

在命名方面, 使用_启动私有方法名称(以及ivar名称)是相对常见的,尽管不是每个人都这样做 – 显然Apple会为自己保留这个名称 ,因此您应该选择不同的前缀。 该语言不强制执行任何操作。

我绝对会使用类扩展。 在实现文件中,在@implementation上面包含类似的@implementation

 @interface A () - (void) doErrorChecking; @end 

然后根据需要在代码中使用该方法。 虽然由于objective-c的动态特性,没有任何方法是真正私有的,但这会使您的接口文件中的方法变得模糊,同时在技术上将其包含在您自己的“私有”接口中。 通常,将.h文件保留为可供公共使用的方法和属性,同时将私有使用方法和属性限制为实现文件中的类扩展。

如果你只需要一个绝对不能被子类覆盖的可​​重用代码集,你可以只创建一个常规的C函数而不是一个方法。 如果函数在类@implementation块的范围内声明,它仍然可以访问该对象的所有私有ivars。 但是,您需要传入指向self的指针,因为函数未绑定到特定对象

所以它看起来像这样:

 static BOOL isInValidState(MyClass *); @implementation MyClass static BOOL isInValidState(MyClass *self) { if (self->somePrivateIvar == nil) { return NO; } if ([self->someString isEqualToString:@"pigsAreFlying"]) { return NO; } return YES; } - (void)method1 { if (isInValidState(self) == NO) { return; } // Do whatever method 1 does } - (void)method2 { if (isInValidState(self) == NO) { return; } // Do whatever method 2 does } @end 

由于函数不是类的方法列表的一部分,因此不能覆盖此错误检查方法。 由于我们将其声明为static ,因此只能在此文件的范围内访问,这意味着它实际上是私有的; 它不能被任何其他类的对象调用。