【问题标题】:Is it possible to declare a second @interface for a category?是否可以为类别声明第二个@interface?
【发布时间】:2012-03-12 09:45:03
【问题描述】:

我正在尝试在 .m 文件中为一个类别声明一个私有 @interface

对于正常的课程,我会这样做:

@interface ClassA ()

@end

@implementation ClassA

@end

它会顺利运行。

对于我尝试过的具有类别的课程:

@interface ClassA (CategoryA) ()

@end

@implementation ClassA (CategoryA)

@end

但它给出了各种不同的错误。我正在尝试“扩展”一个类别,即通过此语法@interface ClassA () 扩展类的方式。

我想拥有该类别的私有方法,并且我想知道,除了公开的接口之外,我是否可以在 .m 文件中放置第二个类别@interface,它不会公开实例变量和类本身之外的方法。

类似这样的:

ClassA+categoryA.h

@interface ClassA (CategoryA)

<some public methods>

@end

ClassA+categoryA.m 文件

@interface ClassA (CategoryA)

<some private methods>

@end


@implementation ClassA (CategoryA)

<here I want to be able to call the private methods above>

@end

现在这在 Xcode 中给了我一个警告:

接口“ClassA”上的类别“CategoryA”的重复定义

有没有办法得到这种行为?

【问题讨论】:

  • -1 的原因是什么?我是不是做错了什么?
  • 有点含糊,你应该提供你所说的错误。但我认为答案已经足够清楚了。
  • 这些错误与这里无关,它们显然是由于 xCode 不理解我尝试应用的语法。
  • 很明显是xCode不理解语法,这是语法错误造成的。
  • 这个问题是问什么是正确的语法来实现我想要的,并知道它是否可能。我对 xCode 告诉我有语法错误没问题,我刚刚猜到语法可能是什么,但我猜错了;)

标签: objective-c class categories


【解决方案1】:

不,您不能为一个类别声明两个接口。您可以执行以下两项操作之一:

Englebert+Humperdinck.h

#import "Englebert.h"

@interface Englebert (Humperdinck)

- (void) croon;

@end

您可以用不同的名称声明 另一个 类别以包含私有方法。然后可以在声明私有类别接口的同一文件中使用它们:

Englebert+Humperdinck.m

#import "Englebert+Humperdinck.h"

@interface Englebert (HumperdinckPrivate)

- (void) warmUp;

@end

@implementation Englebert (HumperdinckPrivate)

- (void)warmUp {
    NSLog(@"Warm up");
}

@end

@implementation Englebert (Humperdinck)

- (void)croon {
    [self warmUp];
    NSLog(@"Croon");
    // etc.
}

@end

另一种选择是不声明私有方法。如果你只是在实现块中定义它们,你可以在定义它们之后在该文件中的任何位置使用它们(对于最新版本的 Xcode/LLVM,顺序实际上并不重要——未声明的方法可以在任何地方使用定义它们的文件)。其他文件将无法看到这些方法。

Englebert+Humperdinck.m

#import "Englebert+Humperdinck.h"

@implementation Englebert (Humperdinck)

/* Undeclared private method */
- (void)warmUp {
    NSLog(@"Warm up");
}

- (void)croon {
    [self warmUp];
    NSLog(@"Croon");
    // etc.
}

@end

【讨论】:

  • 非常感谢乔希。很好解释。我不知道最新的 Xcode 实现顺序不再重要,我会这样。干杯。
  • 您好,我在第一个类别实现文件中声明了第二个类别(就像您在此处显示的那样)。但是我没有为第二类写@implementation,我只是在第一类实现中实现它们。 Xcode 没有抱怨它,那么这是一个“更好”的选择吗? B/C 我的目标是声明那些私有方法,我可以节省一些打字。
【解决方案2】:

@interface ClassA (CategoryA)

@end

@implementation ClassA (CategoryA)

@end

相反。类别不能有实例变量。你在说什么样的错误?

【讨论】:

    【解决方案3】:

    @interface ClassA () 是一个anonymous category,您可以将它们用作接口并在ClassA 实现中定义实现。 @interface ClassA (CategoryA) () 是语法错误,应为 @interface ClassA (CategoryA)

    编辑:

    要为类创建私有方法,在该类的.m 文件中,您将拥有:

    @interface ClassA ()
        // Private functions declared
    @end
    
    @implementation ClassA
        // Private functions defined
        // Other functions defined
    @end
    

    对于命名类别也可以这样做,但是您需要单独定义实现以避免警告。同样,在.m 文件中:

    @interface ClassA (hidden)
        // Private functions declared
    @end
    
    @implementation ClassA (hidden)
        // Private functions declared
    @end
    
    @implementation ClassA
        // Other functions defined
    @end
    

    【讨论】:

    • 这正是我的问题,但不是答案。我在问我是否可以实现一些“私有”方法和实例变量,这些方法和实例变量除了类本身之外不会像我们对没有类别的类所做的那样暴露在外部。我知道如何为我的类类别编写一个接口,但它暴露在外面,我想知道是否有一种语法可以避免在命名类类别之外暴露方法。
    • 这条评论没有意义。您可以通过在实现文件中声明 interface() 来获得类“私有”的方法。您可以在可从任何类使用的特定实例/类上创建类别。你还需要什么?
    • @Rog:我希望能够在 ClassA+CategoryA.m 文件中拥有不暴露给其他类的私有方法。如果您的帖子建议我将它们放在 ClassA.m 文件中,我可能会同意,但我想知道是否允许我将它们放在每个类别的正确 .m 文件中。
    • 我在单独的 .m 和 .h 文件中定义类别时遇到了很多问题,其中没有驻留类(静态库):stackoverflow.com/questions/6029921/…
    • 在您上面的更新中,我们几乎就在那里 Aram 感谢,但这阻止了我公开该类别的其他方法(在 .h 文件中)。我的想法是让 classA+categoryA.h 和 @interface ClassA (CategoryA) 用于公开的方法,而 classA+categoryA.m 和另一个接口(我不知道它的语法)用于我想保持私有的方法类本身。
    猜你喜欢
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 2017-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多