我刚开始编写Objective-C,有Java背景,不知道人们写Objective-C程序是如何处理私有方法的。

我知道可能会有一些约定和习惯,把这个问题看作是人们在Objective-C中处理私有方法时使用的最佳技术的集合。

请包括一个论点,你的方法张贴时。为什么它是好的?你知道它有哪些缺点,你是如何处理它们的?


至于我目前的发现。

可以使用MyClass中定义的类别[例如MyClass (Private)]。M文件对私有方法进行分组。

这种方法有两个问题:

Xcode(和编译器?)不会检查你是否在相应的@implementation块中定义了私有类别中的所有方法 你必须把@interface放在MyClass的开头声明你的私有类别。m文件,否则Xcode抱怨一个消息像“self可能不响应消息“privateFoo”。

第一个问题可以用空类别来解决[例如MyClass()]。 第二个问题让我很困扰。我希望在文件末尾看到私有方法的实现(和定义);我不知道这是否可能。


当前回答

There isn't really a "private method" in Objective-C, if the runtime can work out which implementation to use it will do it. But that's not to say that there aren't methods which aren't part of the documented interface. For those methods I think that a category is fine. Rather than putting the @interface at the top of the .m file like your point 2, I'd put it into its own .h file. A convention I follow (and have seen elsewhere, I think it's an Apple convention as Xcode now gives automatic support for it) is to name such a file after its class and category with a + separating them, so @interface GLObject (PrivateMethods) can be found in GLObject+PrivateMethods.h. The reason for providing the header file is so that you can import it in your unit test classes :-).

顺便说一下,至于在.m文件末尾实现/定义方法,你可以通过在.m文件底部实现category来做到这一点:

@implementation GLObject(PrivateMethods)
- (void)secretFeature;
@end

或者使用类扩展(你称之为“空类别”的东西),最后定义这些方法。Objective-C方法可以在实现中以任何顺序定义和使用,因此没有什么可以阻止您将“私有”方法放在文件的末尾。

即使使用类扩展,我也经常会创建一个单独的头文件(GLObject+Extension.h),以便在需要时使用这些方法,模仿“好友”或“受保护”可见性。

因为这个答案是最初编写的,clang编译器已经开始为Objective-C方法进行两次传递。这意味着你可以完全避免声明你的“私有”方法,无论它们是在调用站点的上面还是下面,它们都会被编译器找到。

其他回答

没有办法绕过问题2。这就是C编译器(以及Objective-C编译器)的工作方式。如果你使用XCode编辑器,函数弹出会让你很容易浏览文件中的@interface和@implementation块。

正如其他人所说,在@implementation块中定义私有方法对于大多数目的来说是可以的。

关于代码组织的话题——我喜欢把它们放在pragma mark private下,以便在Xcode中更容易导航

@implementation MyClass 
// .. public methods

# pragma mark private 
// ...

@end

你可以用积木?

@implementation MyClass

id (^createTheObject)() = ^(){ return [[NSObject alloc] init];};

NSInteger (^addEm)(NSInteger, NSInteger) =
^(NSInteger a, NSInteger b)
{
    return a + b;
};

//public methods, etc.

- (NSObject) thePublicOne
{
    return createTheObject();
}

@end

我知道这是一个古老的问题,但这是我在寻找这个问题答案时最先发现的问题之一。我还没有在其他地方看到过这个解决方案,所以如果这样做有什么愚蠢的地方,请告诉我。

其他人已经说过,Objective-C中没有私有方法。然而,从Objective-C 2.0(意味着Mac OS X Leopard, iPhone OS 2.0和更高版本)开始,你可以创建一个名为类扩展的空名称(即@interface MyClass())的类别。类扩展的独特之处在于方法实现必须与公共方法放在同一个@implementation MyClass中。所以我的课程结构是这样的:

在.h文件中:

@interface MyClass {
    // My Instance Variables
}

- (void)myPublicMethod;

@end

在.m文件中:

@interface MyClass()

- (void)myPrivateMethod;

@end

@implementation MyClass

- (void)myPublicMethod {
    // Implementation goes here
}

- (void)myPrivateMethod {
    // Implementation goes here
}

@end

我认为这种方法最大的优点是,它允许您根据功能对方法实现进行分组,而不是根据(有时是任意的)公共/私有区分进行分组。

还有一件事我在这里没有看到提到——Xcode支持名称为“_private”的。h文件。假设你有一个类。m和myclass。h现在你还可以有myclass_private。h。Xcode会识别它,并将其包含在助理编辑器的“对应项”列表中。

//MyClass.m
#import "MyClass.h"
#import "MyClass_private.h"