Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to declare a second @interface for a category?

I am trying to declare a private @interface for a category, in the .m file.

For a normal class I would do:

@interface ClassA ()

@end

@implementation ClassA

@end

and it would work smoothly.

For a class with categories I tried:

@interface ClassA (CategoryA) ()

@end

@implementation ClassA (CategoryA)

@end

but it is giving all sort of different errors. I am trying to "extend" a category, the way that a class is extended via this syntax @interface ClassA ().

I want to have private methods for the category, and I wanted to know if, IN ADDITION to the exposed interface I am allowed to put a second category @interface in the .m file, which does not expose instance variables and methods outside the class itself.

Something like this:

ClassA+categoryA.h

@interface ClassA (CategoryA)

<some public methods>

@end

ClassA+categoryA.m file

@interface ClassA (CategoryA)

<some private methods>

@end


@implementation ClassA (CategoryA)

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

@end

Right now this is giving me a warning in Xcode:

Duplicate definition of category 'CategoryA' on interface 'ClassA'

Is there any way to get this behavior?

like image 938
Fabrizio Prosperi Avatar asked Mar 12 '12 09:03

Fabrizio Prosperi


1 Answers

No, you can't declare two interfaces for a single category. You can do one of two things:

Englebert+Humperdinck.h

#import "Englebert.h"

@interface Englebert (Humperdinck)

- (void) croon;

@end

You can declare another category with a different name to contain the private methods. These can then be used in the same file where the private category interface is declared:

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

The other option is to simply not declare the private methods. If you just define them in the implementation block, you can use them at any point in that file after they are defined (and for the latest version of Xcode/LLVM, the order is in fact unimportant -- undeclared methods can be used anywhere in the file in which they are defined). No other files will be able to see these methods.

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
like image 97
jscs Avatar answered Nov 15 '22 15:11

jscs